Add seconds elapsed to heaptrack log for future evaluation.
authorMilian Wolff <mail@milianw.de>
Thu, 27 Nov 2014 14:50:16 +0000 (15:50 +0100)
committerMilian Wolff <mail@milianw.de>
Thu, 27 Nov 2014 15:02:44 +0000 (16:02 +0100)
CMakeLists.txt
heaptrack_print.cpp
libheaptrack.cpp
timer.h [new file with mode: 0644]

index 49b3c85..4506b00 100644 (file)
@@ -19,7 +19,7 @@ include_directories(
 add_library(libheaptrack SHARED libheaptrack.cpp)
 # the final .so should be named libheaptrack, not liblibheaptrack
 set_target_properties(libheaptrack PROPERTIES OUTPUT_NAME heaptrack)
-target_link_libraries(libheaptrack ${CMAKE_DL_LIBS} backtrace)
+target_link_libraries(libheaptrack ${CMAKE_DL_LIBS} backtrace rt)
 
 add_executable(heaptrack_interpret heaptrack_interpret.cpp)
 target_link_libraries(heaptrack_interpret backtrace)
index ce8c4ab..31173da 100644 (file)
@@ -509,6 +509,8 @@ struct AccumulatedTraceData
             } else if (reader.mode() == '#') {
                 // comment or empty line
                 continue;
+            } else if (reader.mode() == 'c') {
+                // TODO: implement time tracking
             } else {
                 cerr << "failed to parse line: " << reader.line() << endl;
             }
index 1414b9c..34e76e7 100644 (file)
@@ -40,6 +40,7 @@
 #include <link.h>
 
 #include "tracetree.h"
+#include "timer.h"
 
 /**
  * uncomment this to get extended debug code for known pointers
@@ -157,6 +158,8 @@ struct Data
         // cleanup environment to prevent tracing of child apps
         unsetenv("DUMP_HEAPTRACK_OUTPUT");
         unsetenv("LD_PRELOAD");
+
+        timer.setInterval(1, 0);
     }
 
     ~Data()
@@ -220,7 +223,10 @@ struct Data
         }
 
         LockGuard lock(out);
-
+        if (lastTimerElapsed != timer.timesElapsed()) {
+            lastTimerElapsed = timer.timesElapsed();
+            fprintf(out, "c %lx\n", lastTimerElapsed);
+        }
         if (moduleCacheDirty) {
             updateModuleCache();
         }
@@ -256,10 +262,14 @@ struct Data
      */
     FILE* out = nullptr;
 
+    size_t lastTimerElapsed = 0;
+    Timer timer;
+
     bool foundExe = false;
 #ifdef DEBUG_MALLOC_PTRS
     unordered_set<void*> known;
 #endif
+
 };
 
 unique_ptr<Data> data;
diff --git a/timer.h b/timer.h
new file mode 100644 (file)
index 0000000..e308261
--- /dev/null
+++ b/timer.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2014 Milian Wolff <mail@milianw.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TIMER_H
+#define TIMER_H
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <cassert>
+
+#include <limits>
+
+class Timer
+{
+public:
+    Timer()
+        : m_timesElapsed(0)
+        , m_timerId(0)
+    {
+        /* Establish handler for timer signal */
+
+        struct sigaction sa;
+        sa.sa_flags = SA_SIGINFO;
+        sa.sa_sigaction = &Timer::handler;
+        sigemptyset(&sa.sa_mask);
+        if (sigaction(SIGRTMIN, &sa, nullptr) == -1) {
+            fprintf(stderr, "Failed to call sigaction in %s:%d: %s",
+                    __FILE__, __LINE__, strerror(errno));
+            return;
+        }
+
+        /* Create the timer */
+
+        sigevent sev;
+        sev.sigev_notify = SIGEV_SIGNAL;
+        sev.sigev_signo = SIGRTMIN;
+        sev.sigev_value.sival_ptr = this;
+        if (timer_create(CLOCK_REALTIME, &sev, &m_timerId) == -1) {
+            fprintf(stderr, "Failed to call timer_create in %s:%d: %s",
+                    __FILE__, __LINE__, strerror(errno));
+            return;
+        }
+    }
+
+    ~Timer()
+    {
+        timer_delete(m_timerId);
+    }
+
+    size_t timesElapsed() const
+    {
+        return m_timesElapsed;
+    }
+
+    void setInterval(time_t seconds, long long nanoseconds)
+    {
+        /* Start/Stop the timer */
+        itimerspec its;
+        its.it_value.tv_sec = seconds;
+        its.it_value.tv_nsec = nanoseconds;
+        its.it_interval.tv_sec = seconds;
+        its.it_interval.tv_nsec = nanoseconds;
+
+        if (timer_settime(m_timerId, 0, &its, nullptr) == -1) {
+            fprintf(stderr, "Failed to call timer_settime in %s:%d: %s",
+                    __FILE__, __LINE__, strerror(errno));
+            return;
+        }
+    }
+
+private:
+    static void handler(int /*sig*/, siginfo_t *si, void */*uc*/)
+    {
+        auto overrun = si->si_overrun;
+        if (overrun < 0) {
+            return;
+        }
+
+        Timer* timer = static_cast<Timer*>(si->si_value.sival_ptr);
+        timer->m_timesElapsed += overrun + 1;
+    }
+
+    size_t m_timesElapsed;
+    timer_t m_timerId;
+};
+
+#endif