]> git.cworth.org Git - apitrace/blobdiff - common/trace_profiler.cpp
Extend profiling tool to support Vsize and Rss memory usage profile per call
[apitrace] / common / trace_profiler.cpp
index fd684ede7bf16d623b7b54b9f80e67477aaf8bc8..773e7cc4096876090087b6c14c3753089e674eda 100644 (file)
@@ -1,6 +1,7 @@
 /**************************************************************************
  *
  * Copyright 2012 VMware, Inc.
+ * Copyright 2013 Intel, Inc.
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
  **************************************************************************/
 
 #include "trace_profiler.hpp"
+#include "os_time.hpp"
 #include <iostream>
+#include <string.h>
+#include <sstream>
 
 namespace trace {
 Profiler::Profiler()
-    : baseTime(0)
+    : baseGpuTime(0),
+      baseCpuTime(0),
+      minCpuTime(1000),
+      baseVsizeUsage(0),
+      baseRssUsage(0),
+      cpuTimes(false),
+      gpuTimes(true),
+      pixelsDrawn(false),
+      memoryUsage(false)
 {
 }
 
@@ -36,41 +48,215 @@ Profiler::~Profiler()
 {
 }
 
-void Profiler::addCall(unsigned no, const char *name, uint64_t gpu_start, uint64_t gpu_duration)
+void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_, bool memoryUsage_)
 {
-    if (baseTime == 0)
-        baseTime = gpu_start;
+    cpuTimes = cpuTimes_;
+    gpuTimes = gpuTimes_;
+    pixelsDrawn = pixelsDrawn_;
+    memoryUsage = memoryUsage_;
 
-    std::cout << "call "
-              << no << " "
-              << (gpu_start - baseTime) << " "
-              << gpu_duration << " "
-              << name << std::endl;
+    std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura vsize_start vsize_dura rss_start rss_dura pixels program name" << std::endl;
 }
 
-void Profiler::addFrameStart(unsigned no, uint64_t timestamp)
+int64_t Profiler::getBaseCpuTime()
 {
-    if (baseTime == 0)
-        baseTime = timestamp;
+    return baseCpuTime;
+}
+
+int64_t Profiler::getBaseGpuTime()
+{
+    return baseGpuTime;
+}
+
+int64_t Profiler::getBaseVsizeUsage()
+{
+    return baseVsizeUsage;
+}
+
+int64_t Profiler::getBaseRssUsage()
+{
+    return baseRssUsage;
+}
+
+void Profiler::setBaseCpuTime(int64_t cpuStart)
+{
+    baseCpuTime = cpuStart;
+}
+
+void Profiler::setBaseGpuTime(int64_t gpuStart)
+{
+    baseGpuTime = gpuStart;
+}
+
+void Profiler::setBaseVsizeUsage(int64_t vsizeStart)
+{
+    baseVsizeUsage = vsizeStart;
+}
+
+void Profiler::setBaseRssUsage(int64_t rssStart)
+{
+    baseRssUsage = rssStart;
+}
+
+bool Profiler::hasBaseTimes()
+{
+    return baseCpuTime != 0 || baseGpuTime != 0;
+}
+
+void Profiler::addCall(unsigned no,
+                       const char *name,
+                       unsigned program,
+                       int64_t pixels,
+                       int64_t gpuStart, int64_t gpuDuration,
+                       int64_t cpuStart, int64_t cpuDuration,
+                       int64_t vsizeStart, int64_t vsizeDuration,
+                       int64_t rssStart, int64_t rssDuration)
+{
+    if (gpuTimes && gpuStart) {
+        gpuStart -= baseGpuTime;
+    } else {
+        gpuStart = 0;
+        gpuDuration = 0;
+    }
+
+    if (cpuTimes && cpuStart) {
+        double cpuTimeScale = 1.0E9 / os::timeFrequency;
+        cpuStart = (cpuStart - baseCpuTime) * cpuTimeScale;
+        cpuDuration = cpuDuration * cpuTimeScale;
+
+        if (cpuDuration < minCpuTime) {
+            return;
+        }
+    } else {
+        cpuStart = 0;
+        cpuDuration = 0;
+    }
 
-    lastFrame.no = no;
-    lastFrame.start = timestamp - baseTime;
+    if (!pixelsDrawn) {
+        pixels = 0;
+    }
 
-    std::cout << "frame begin "
-              << lastFrame.no << " "
-              << lastFrame.start << std::endl;
+    if (!memoryUsage || !vsizeStart || !rssStart) {
+        vsizeStart = 0;
+        vsizeDuration = 0;
+        rssStart = 0;
+        rssDuration = 0;
+    }
+
+    std::cout << "call"
+              << " " << no
+              << " " << gpuStart
+              << " " << gpuDuration
+              << " " << cpuStart
+              << " " << cpuDuration
+              << " " << vsizeStart
+              << " " << vsizeDuration
+              << " " << rssStart
+              << " " << rssDuration
+              << " " << pixels
+              << " " << program
+              << " " << name
+              << std::endl;
+}
+
+void Profiler::addFrameEnd()
+{
+    std::cout << "frame_end" << std::endl;
 }
 
-void Profiler::addFrameEnd(uint64_t timestamp)
+void Profiler::parseLine(const char* in, Profile* profile)
 {
-    if (baseTime == 0)
-        baseTime = timestamp;
+    std::stringstream line(in, std::ios_base::in);
+    std::string type;
+    static int64_t lastGpuTime;
+    static int64_t lastCpuTime;
+    static int64_t lastVsizeUsage;
+    static int64_t lastRssUsage;
+
+    if (in[0] == '#' || strlen(in) < 4)
+        return;
+
+    if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
+        lastGpuTime = 0;
+        lastCpuTime = 0;
+        lastVsizeUsage = 0;
+        lastRssUsage = 0;
+    }
+
+    line >> type;
+
+    if (type.compare("call") == 0) {
+        Profile::Call call;
+
+        line >> call.no
+             >> call.gpuStart
+             >> call.gpuDuration
+             >> call.cpuStart
+             >> call.cpuDuration
+             >> call.vsizeStart
+             >> call.vsizeDuration
+             >> call.rssStart
+             >> call.rssDuration
+             >> call.pixels
+             >> call.program
+             >> call.name;
+
+        if (lastGpuTime < call.gpuStart + call.gpuDuration) {
+            lastGpuTime = call.gpuStart + call.gpuDuration;
+        }
+
+        if (lastCpuTime < call.cpuStart + call.cpuDuration) {
+            lastCpuTime = call.cpuStart + call.cpuDuration;
+        }
+
+        if (lastVsizeUsage < call.vsizeStart + call.vsizeDuration) {
+            lastVsizeUsage = call.vsizeStart + call.vsizeDuration;
+        }
+
+        if (lastRssUsage < call.rssStart + call.rssDuration) {
+            lastRssUsage = call.rssStart + call.rssDuration;
+        }
+
+        profile->calls.push_back(call);
+
+        if (call.pixels >= 0) {
+            if (profile->programs.size() <= call.program) {
+                profile->programs.resize(call.program + 1);
+            }
+
+            Profile::Program& program = profile->programs[call.program];
+            program.cpuTotal += call.cpuDuration;
+            program.gpuTotal += call.gpuDuration;
+            program.pixelTotal += call.pixels;
+            program.vsizeTotal += call.vsizeDuration;
+            program.rssTotal += call.rssDuration;
+            program.calls.push_back(profile->calls.size() - 1);
+        }
+    } else if (type.compare("frame_end") == 0) {
+        Profile::Frame frame;
+        frame.no = profile->frames.size();
+
+        if (frame.no == 0) {
+            frame.gpuStart = 0;
+            frame.cpuStart = 0;
+            frame.vsizeStart = 0;
+            frame.rssStart = 0;
+            frame.calls.begin = 0;
+        } else {
+            frame.gpuStart = profile->frames.back().gpuStart + profile->frames.back().gpuDuration;
+            frame.cpuStart = profile->frames.back().cpuStart + profile->frames.back().cpuDuration;
+            frame.vsizeStart = profile->frames.back().vsizeStart + profile->frames.back().vsizeDuration;
+            frame.rssStart = profile->frames.back().rssStart + profile->frames.back().rssDuration;
+            frame.calls.begin = profile->frames.back().calls.end + 1;
+        }
 
-    lastFrame.end = timestamp - baseTime;
+        frame.gpuDuration = lastGpuTime - frame.gpuStart;
+        frame.cpuDuration = lastCpuTime - frame.cpuStart;
+        frame.vsizeDuration = lastVsizeUsage - frame.vsizeStart;
+        frame.rssDuration = lastRssUsage - frame.rssStart;
+        frame.calls.end = profile->calls.size() - 1;
 
-    std::cout << "frame end "
-              << lastFrame.no << " "
-              << lastFrame.end << " "
-              << (lastFrame.end - lastFrame.start) << std::endl;
+        profile->frames.push_back(frame);
+    }
 }
 }