]> git.cworth.org Git - apitrace/commitdiff
Extend profiling tool to support Vsize and Rss memory usage profile per call
authorShuang He <shuang.he@intel.com>
Mon, 18 Feb 2013 02:09:44 +0000 (10:09 +0800)
committerJosé Fonseca <jfonseca@vmware.com>
Mon, 4 Mar 2013 20:11:41 +0000 (20:11 +0000)
Add one new option -pmem for retrace tool to track Visze and Rss usage during every call

Signed-off-by: Shuang He <shuang.he@intel.com>
Signed-off-by: José Fonseca <jfonseca@vmware.com>
CMakeLists.txt
common/os_memory.hpp [new file with mode: 0644]
common/trace_profiler.cpp
common/trace_profiler.hpp
retrace/CMakeLists.txt
retrace/glretrace_main.cpp
retrace/retrace.hpp
retrace/retrace_main.cpp

index 91f1b874321caea66abf4cec2ed5597748d68c87..90bfc870aade3941c9ab3a5c769e9873010f550a 100644 (file)
@@ -191,6 +191,10 @@ if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
         ERROR_QUIET
         OUTPUT_STRIP_TRAILING_WHITESPACE
     )
+    CHECK_INCLUDE_FILES(proc/readproc.h READPROC_H_FOUND)
+    if (READPROC_H_FOUND)
+        add_definitions (-DHAVE_READPROC_H)
+    endif ()
 endif()
 
 if (WIN32 OR APPLE)
diff --git a/common/os_memory.hpp b/common/os_memory.hpp
new file mode 100644 (file)
index 0000000..4774412
--- /dev/null
@@ -0,0 +1,67 @@
+/**************************************************************************
+ *
+ * Copyright (C) 2013 Intel Corporation. All rights reversed.
+ * Author: Shuang He <shuang.he@intel.com>
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ **************************************************************************/
+
+/*
+ * Simple OS time measurement abstraction.
+ */
+
+#ifndef _OS_MEMORY_HPP_
+#define _OS_MEMORY_HPP_
+
+#ifdef HAVE_READPROC_H
+#include <proc/readproc.h>
+
+namespace os {
+    inline long long
+    getVsize(void) {
+        proc_t proc;
+        look_up_our_self(&proc);
+        return proc.vsize;
+    }
+
+    inline long long
+    getRss(void) {
+        proc_t proc;
+        look_up_our_self(&proc);
+        return proc.rss;
+    }
+} /* namespace os */
+
+#else
+namespace os {
+    inline long long
+    getVsize(void) {
+        return 0;
+    }
+
+    inline long long
+    getRss(void) {
+        return 0;
+    }
+} /* namespace os */
+#endif
+
+#endif /* _OS_MEMORY_HPP_ */
index 0f90ee2766318c54f790fc110efd772b8126f309..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
@@ -34,9 +35,12 @@ Profiler::Profiler()
     : baseGpuTime(0),
       baseCpuTime(0),
       minCpuTime(1000),
+      baseVsizeUsage(0),
+      baseRssUsage(0),
       cpuTimes(false),
       gpuTimes(true),
-      pixelsDrawn(false)
+      pixelsDrawn(false),
+      memoryUsage(false)
 {
 }
 
@@ -44,13 +48,14 @@ Profiler::~Profiler()
 {
 }
 
-void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_)
+void Profiler::setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_, bool memoryUsage_)
 {
     cpuTimes = cpuTimes_;
     gpuTimes = gpuTimes_;
     pixelsDrawn = pixelsDrawn_;
+    memoryUsage = memoryUsage_;
 
-    std::cout << "# call no gpu_start gpu_dura cpu_start cpu_dura pixels program 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;
 }
 
 int64_t Profiler::getBaseCpuTime()
@@ -63,6 +68,16 @@ 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;
@@ -73,6 +88,16 @@ 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;
@@ -83,7 +108,9 @@ void Profiler::addCall(unsigned no,
                        unsigned program,
                        int64_t pixels,
                        int64_t gpuStart, int64_t gpuDuration,
-                       int64_t cpuStart, int64_t cpuDuration)
+                       int64_t cpuStart, int64_t cpuDuration,
+                       int64_t vsizeStart, int64_t vsizeDuration,
+                       int64_t rssStart, int64_t rssDuration)
 {
     if (gpuTimes && gpuStart) {
         gpuStart -= baseGpuTime;
@@ -109,12 +136,23 @@ void Profiler::addCall(unsigned no,
         pixels = 0;
     }
 
+    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
@@ -132,6 +170,8 @@ void Profiler::parseLine(const char* in, Profile* profile)
     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;
@@ -139,6 +179,8 @@ void Profiler::parseLine(const char* in, Profile* profile)
     if (profile->programs.size() == 0 && profile->calls.size() == 0 && profile->frames.size() == 0) {
         lastGpuTime = 0;
         lastCpuTime = 0;
+        lastVsizeUsage = 0;
+        lastRssUsage = 0;
     }
 
     line >> type;
@@ -151,6 +193,10 @@ void Profiler::parseLine(const char* in, Profile* profile)
              >> call.gpuDuration
              >> call.cpuStart
              >> call.cpuDuration
+             >> call.vsizeStart
+             >> call.vsizeDuration
+             >> call.rssStart
+             >> call.rssDuration
              >> call.pixels
              >> call.program
              >> call.name;
@@ -163,6 +209,14 @@ void Profiler::parseLine(const char* in, Profile* profile)
             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) {
@@ -174,6 +228,8 @@ void Profiler::parseLine(const char* in, Profile* profile)
             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) {
@@ -183,15 +239,21 @@ void Profiler::parseLine(const char* in, Profile* profile)
         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;
         }
 
         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;
 
         profile->frames.push_back(frame);
index d8332420c63fc6ce622fd300315d275a85ba0db2..e3ae016be7fa654b99e497e64fdc3c7ef914cfb8 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
@@ -45,6 +46,11 @@ struct Profile {
         int64_t cpuStart;
         int64_t cpuDuration;
 
+        int64_t vsizeStart;
+        int64_t vsizeDuration;
+        int64_t rssStart;
+        int64_t rssDuration;
+
         int64_t pixels;
 
         std::string name;
@@ -59,6 +65,11 @@ struct Profile {
         int64_t cpuStart;
         int64_t cpuDuration;
 
+        int64_t vsizeStart;
+        int64_t vsizeDuration;
+        int64_t rssStart;
+        int64_t rssDuration;
+
         /* Indices to profile->calls array */
         struct {
             unsigned begin;
@@ -72,6 +83,8 @@ struct Profile {
         uint64_t gpuTotal;
         uint64_t cpuTotal;
         uint64_t pixelTotal;
+        int64_t vsizeTotal;
+        int64_t rssTotal;
 
         /* Indices to profile->calls array */
         std::vector<unsigned> calls;
@@ -88,14 +101,16 @@ public:
     Profiler();
     ~Profiler();
 
-    void setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_);
+    void setup(bool cpuTimes_, bool gpuTimes_, bool pixelsDrawn_, bool memoryUsage_);
 
     void 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 cpuStart, int64_t cpuDuration,
+                 int64_t vsizeStart, int64_t vsizeDuration,
+                 int64_t rssStart, int64_t rssDuration);
 
     void addFrameEnd();
 
@@ -103,9 +118,13 @@ public:
 
     void setBaseCpuTime(int64_t cpuStart);
     void setBaseGpuTime(int64_t gpuStart);
+    void setBaseVsizeUsage(int64_t vsizeStart);
+    void setBaseRssUsage(int64_t rssStart);
 
     int64_t getBaseCpuTime();
     int64_t getBaseGpuTime();
+    int64_t getBaseVsizeUsage();
+    int64_t getBaseRssUsage();
 
     static void parseLine(const char* line, Profile* profile);
 
@@ -113,10 +132,13 @@ private:
     int64_t baseGpuTime;
     int64_t baseCpuTime;
     int64_t minCpuTime;
+    int64_t baseVsizeUsage;
+    int64_t baseRssUsage;
 
     bool cpuTimes;
     bool gpuTimes;
     bool pixelsDrawn;
+    bool memoryUsage;
 };
 }
 
index b271727458bb2d6db722c045eaee1eb193dbe4c5..9ea1ae9998e68587f67c43498ded0790b9769657 100644 (file)
@@ -102,6 +102,9 @@ if (WIN32 OR APPLE OR X11_FOUND)
 
         if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
             target_link_libraries (glretrace rt)
+            if (READPROC_H_FOUND)
+                target_link_libraries (glretrace proc)
+            endif ()
         endif ()
 
     endif ()
@@ -127,6 +130,9 @@ if (ENABLE_EGL AND X11_FOUND AND NOT WIN32 AND NOT APPLE)
 
     if (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
         target_link_libraries (eglretrace rt)
+        if (READPROC_H_FOUND)
+            target_link_libraries (eglretrace proc)
+        endif ()
     endif ()
 
     install (TARGETS eglretrace RUNTIME DESTINATION bin) 
index f369b33b7316c0f2c7ce7181268ba2c8736bbcaa..1591287c22d9d254507dba27a23c5245a5e83d20 100755 (executable)
@@ -1,6 +1,8 @@
 /**************************************************************************
  *
  * Copyright 2011 Jose Fonseca
+ * Copyright (C) 2013 Intel Corporation. All rights reversed.
+ * Author: Shuang He <shuang.he@intel.com>
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -31,6 +33,7 @@
 #include "glstate.hpp"
 #include "glretrace.hpp"
 #include "os_time.hpp"
+#include "os_memory.hpp"
 
 /* Synchronous debug output may reduce performance however,
  * without it the callNo in the callback may be inaccurate
@@ -60,6 +63,10 @@ struct CallQuery
     const trace::FunctionSig *sig;
     int64_t cpuStart;
     int64_t cpuEnd;
+    int64_t vsizeStart;
+    int64_t vsizeEnd;
+    int64_t rssStart;
+    int64_t rssEnd;
 };
 
 static bool supportsElapsed = true;
@@ -138,10 +145,20 @@ getTimeFrequency(void) {
     }
 }
 
+static inline void
+getCurrentVsize(int64_t& vsize) {
+    vsize = os::getVsize();
+}
+
+static inline void
+getCurrentRss(int64_t& rss) {
+    rss = os::getRss();
+}
+
 static void
 completeCallQuery(CallQuery& query) {
     /* Get call start and duration */
-    int64_t gpuStart = 0, gpuDuration = 0, cpuDuration = 0, pixels = 0;
+    int64_t gpuStart = 0, gpuDuration = 0, cpuDuration = 0, pixels = 0, vsizeDuration = 0, rssDuration = 0;
 
     if (query.isDraw) {
         if (retrace::profilingGpuTimes) {
@@ -164,10 +181,15 @@ completeCallQuery(CallQuery& query) {
         cpuDuration = query.cpuEnd - query.cpuStart;
     }
 
+    if (retrace::profilingMemoryUsage) {
+        vsizeDuration = query.vsizeEnd - query.vsizeStart;
+        rssDuration = query.rssEnd - query.rssStart;
+    }
+
     glDeleteQueries(NUM_QUERIES, query.ids);
 
     /* Add call to profile */
-    retrace::profiler.addCall(query.call, query.sig->name, query.program, pixels, gpuStart, gpuDuration, query.cpuStart, cpuDuration);
+    retrace::profiler.addCall(query.call, query.sig->name, query.program, pixels, gpuStart, gpuDuration, query.cpuStart, cpuDuration, query.vsizeStart, vsizeDuration, query.rssStart, rssDuration);
 }
 
 void
@@ -214,6 +236,12 @@ beginProfile(trace::Call &call, bool isDraw) {
         CallQuery& query = callQueries.back();
         query.cpuStart = getCurrentTime();
     }
+
+    if (retrace::profilingMemoryUsage) {
+        CallQuery& query = callQueries.back();
+        query.vsizeStart = os::getVsize();
+        query.rssStart = os::getRss();
+    }
 }
 
 void
@@ -235,6 +263,12 @@ endProfile(trace::Call &call, bool isDraw) {
             glEndQuery(GL_SAMPLES_PASSED);
         }
     }
+
+    if (retrace::profilingMemoryUsage) {
+        CallQuery& query = callQueries.back();
+        query.vsizeEnd = os::getVsize();
+        query.rssEnd = os::getRss();
+    }
 }
 
 void
@@ -289,6 +323,14 @@ initContext() {
             retrace::profiler.setBaseGpuTime(currentTime);
         }
     }
+
+    if (retrace::profilingMemoryUsage) {
+        GLint64 currentVsize, currentRss;
+        getCurrentVsize(currentVsize);
+        retrace::profiler.setBaseVsizeUsage(currentVsize);
+        getCurrentRss(currentRss);
+        retrace::profiler.setBaseRssUsage(currentRss);
+    }
 }
 
 void
index 7c8dcd5229426743bf52a52c0609b5fb84e0fb0b..14317cffbe96d7cbbe70c718127e537ea9aff5a1 100644 (file)
@@ -1,6 +1,8 @@
 /**************************************************************************
  *
  * Copyright 2011-2012 Jose Fonseca
+ * Copyright (C) 2013 Intel Corporation. All rights reversed.
+ * Author: Shuang He <shuang.he@intel.com>
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -92,6 +94,7 @@ extern bool profiling;
 extern bool profilingCpuTimes;
 extern bool profilingGpuTimes;
 extern bool profilingPixelsDrawn;
+extern bool profilingMemoryUsage;
 
 /**
  * State dumping.
index ca03745c64d241ba836f718ca7aef041c2749cbc..7cc3fcab869bf0e5935d504838275de4909bd940 100644 (file)
@@ -1,6 +1,8 @@
 /**************************************************************************
  *
  * Copyright 2011 Jose Fonseca
+ * Copyright (C) 2013 Intel Corporation. All rights reversed.
+ * Author: Shuang He <shuang.he@intel.com>
  * All Rights Reserved.
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -72,6 +74,7 @@ bool profiling = false;
 bool profilingGpuTimes = false;
 bool profilingCpuTimes = false;
 bool profilingPixelsDrawn = false;
+bool profilingMemoryUsage = false;
 bool useCallNos = true;
 
 unsigned frameNo = 0;
@@ -514,6 +517,7 @@ usage(const char *argv0) {
         "      --pcpu              cpu profiling (cpu times per call)\n"
         "      --pgpu              gpu profiling (gpu times per draw call)\n"
         "      --ppd               pixels drawn profiling (pixels drawn per draw call)\n"
+        "      --pmem              memory usage profiling (vsize rss per call)\n"
         "  -c, --compare=PREFIX    compare against snapshots with given PREFIX\n"
         "  -C, --calls=CALLSET     calls to compare (default is every frame)\n"
         "      --call-nos[=BOOL]   use call numbers in snapshot filenames\n"
@@ -536,6 +540,7 @@ enum {
     PCPU_OPT,
     PGPU_OPT,
     PPD_OPT,
+    PMEM_OPT,
     SB_OPT,
 };
 
@@ -556,6 +561,7 @@ longOptions[] = {
     {"pcpu", no_argument, 0, PCPU_OPT},
     {"pgpu", no_argument, 0, PGPU_OPT},
     {"ppd", no_argument, 0, PPD_OPT},
+    {"pmem", no_argument, 0, PMEM_OPT},
     {"sb", no_argument, 0, SB_OPT},
     {"snapshot-prefix", required_argument, 0, 's'},
     {"snapshot", required_argument, 0, 'S'},
@@ -676,6 +682,13 @@ int main(int argc, char **argv)
 
             retrace::profilingPixelsDrawn = true;
             break;
+        case PMEM_OPT:
+            retrace::debug = false;
+            retrace::profiling = true;
+            retrace::verbosity = -1;
+
+            retrace::profilingMemoryUsage = true;
+            break;
         default:
             std::cerr << "error: unknown option " << opt << "\n";
             usage(argv[0]);
@@ -685,7 +698,7 @@ int main(int argc, char **argv)
 
     retrace::setUp();
     if (retrace::profiling) {
-        retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn);
+        retrace::profiler.setup(retrace::profilingCpuTimes, retrace::profilingGpuTimes, retrace::profilingPixelsDrawn, retrace::profilingMemoryUsage);
     }
 
     os::setExceptionCallback(exceptionCallback);