{"id":3989,"date":"2018-05-23T12:05:44","date_gmt":"2018-05-23T19:05:44","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=3989"},"modified":"2018-05-24T16:48:56","modified_gmt":"2018-05-24T23:48:56","slug":"using-live-profiling-to-analyze-critical-parts-of-linux-code","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/profiler\/linux\/live\/","title":{"rendered":"Using Live Profiling to Analyze Critical Parts of Linux Code"},"content":{"rendered":"<p>This tutorial shows how to use the Live Profiling\u00a0for Linux programs to analyze the relative performance of the critical\u00a0code without slowing down the entire program. We will create a basic program that will be sorting an array of 10000 random numbers and will\u00a0use Live Profiling to quickly compare different\u00a0ways\u00a0of doing that without\u00a0profiling the entire program run.<\/p>\n<p>Before you begin, install Visual Studio and VisualGDB 5.3 or later.<\/p>\n<ol>\n<li>Start Visual Studio and open the VisualGDB Linux Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3990\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj.png\" alt=\"01-newprj\" width=\"941\" height=\"653\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj.png 941w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj-300x208.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj-392x272.png 392w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/01-newprj-130x90.png 130w\" sizes=\"(max-width: 941px) 100vw, 941px\" \/><\/a><\/li>\n<li>Select &#8220;Create a new project -&gt; Application -&gt; MSBuild&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/02-msb.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3991\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/02-msb.png\" alt=\"02-msb\" width=\"886\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/02-msb.png 886w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/02-msb-300x235.png 300w\" sizes=\"(max-width: 886px) 100vw, 886px\" \/><\/a><\/li>\n<li>On the next page pick the remote\u00a0Linux machine you are targeting and click &#8220;Next&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/03-remotehost.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3992\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/03-remotehost.png\" alt=\"03-remotehost\" width=\"886\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/03-remotehost.png 886w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/03-remotehost-300x235.png 300w\" sizes=\"(max-width: 886px) 100vw, 886px\" \/><\/a><\/li>\n<li>On the last page of the wizard proceed with the default file access options (Store locally &amp; upload):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/04-access.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3993\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/04-access.png\" alt=\"04-access\" width=\"886\" height=\"693\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/04-access.png 886w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/04-access-300x235.png 300w\" sizes=\"(max-width: 886px) 100vw, 886px\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to create the project. Then replace the contents of the main file with the following code:\n<pre class=\"\">#include &lt;iostream&gt;\r\n#include &lt;vector&gt;\r\n#include &lt;stdio.h&gt;\r\n#include &lt;algorithm&gt;\r\n\r\nusing namespace std;\r\n\r\nvoid TestSorting()\r\n{\r\n    std::vector&lt;int&gt; values;\r\n    for (int i = 0; i &lt; 10000; i++)\r\n        values.push_back(rand());\r\n\r\n    std::sort(values.begin(), values.end());\r\n}\r\n\r\nint main(int argc, char *argv[])\r\n{\r\n    cout &lt;&lt; \"Ready to test\";\r\n    TestSorting();\r\n    return 0;\r\n}<\/pre>\n<\/li>\n<li>Build the solution via Ctrl-Shift-B and set a breakpoint on the std::sort() call:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/05-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3994\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/05-build.png\" alt=\"05-build\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/05-build.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/05-build-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/05-build-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>Now we will use Live Profiling to automatically measure the exact time\u00a0taken by the sort() call (and highlight the critical path). VisualGDB will use this by automatically launching the valgrind tool behind the scenes and interpreting the profiling data it reports. Select Analyze -&gt; Analyze Performance with VisualGDB:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/06-analyze.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3995\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/06-analyze.png\" alt=\"06-analyze\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/06-analyze.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/06-analyze-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/06-analyze-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>If you wanted to profile the entire program, you could simply select &#8220;Profile without debugging&#8221; or &#8220;Profile with debugging&#8221;, however this would result in a significant slowdown as the entire program execution would be\u00a0logged\u00a0in order to\u00a0analyze its performance. While this is acceptable for small programs, it could reduce the overall usability if the critical part of the code\u00a0is\u00a0not reached immediately. To\u00a0facilitate this scenario, VisualGDB provides the Live Profiling mode where it\u00a0will launch valrgind in the\u00a0suspended state and will only profile the code\u00a0once you explicitly\u00a0enable it. Select &#8220;Debug and get ready to profile&#8221; and click OK:<br \/>\n<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/07-startprof.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3996\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/07-startprof.png\" alt=\"07-startprof\" width=\"584\" height=\"469\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/07-startprof.png 584w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/07-startprof-300x241.png 300w\" sizes=\"(max-width: 584px) 100vw, 584px\" \/><\/a><\/li>\n<li>If your remote machine does not have valgrind installed, VisualGDB will offer installing it automatically:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/08-valgrind.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3997\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/08-valgrind.png\" alt=\"08-valgrind\" width=\"737\" height=\"164\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/08-valgrind.png 737w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/08-valgrind-300x67.png 300w\" sizes=\"(max-width: 737px) 100vw, 737px\" \/><\/a><\/li>\n<li>Wait for the breakpoint to hit. Then locate the Live Profiling window and click &#8220;Start profiling&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/09-start.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3998\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/09-start.png\" alt=\"09-start\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/09-start.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/09-start-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/09-start-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>Step over the call to std::sort() and click &#8220;Stop profiling &amp; display results&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/10-stop.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-3999\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/10-stop.png\" alt=\"10-stop\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/10-stop.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/10-stop-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/10-stop-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>VisualGDB will display the profiling results in the Live Profiling window.\u00a0In our example the call to std::sort() involved ~14M instructions mostly from __introsort_loop():<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/11-stats.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4000\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/11-stats.png\" alt=\"11-stats\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/11-stats.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/11-stats-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/11-stats-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>Now\u00a0we will see what happens if we\u00a0replace\u00a0std::sort() with the qsort() function from the standard C library:\n<pre class=\"\">#include &lt;stdlib.h&gt;\r\nint CompareIntegers(const void * a, const void * b)\r\n{\r\n    return (*(int*)a - *(int*)b);\r\n}\r\n\r\nvoid TestSorting()\r\n{\r\n    \/\/...\r\n    qsort(values.data(), values.size(), sizeof(values[0]), CompareIntegers);\r\n}<\/pre>\n<\/li>\n<li>Run the\u00a0live profiling again, enabling the actual profiling only for the qsort() call and observe that the sorting time is almost 3x less: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/12-qsort.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4001\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/12-qsort.png\" alt=\"12-qsort\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/12-qsort.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/12-qsort-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/12-qsort-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a>Note that\u00a0each run of our program will generate exactly the same pseudo-random numbers, as we are not changing the random number generator seed by calling srand().<\/li>\n<li>In this example the qsort() function works faster than std::sort() because it\u00a0is implemented in an external library (build with optimization),\u00a0while this std::sort() code is built in-place with no optimization. In order to compare the\u00a0optimized version of std::sort(), switch to the Release configuration and add <strong>asm(&#8220;nop&#8221;)<\/strong> statements around the call. Then set breakpoints in both statements and\u00a0run the profiling between the breakpoint hits:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/13-faster.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4002\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/13-faster.png\" alt=\"13-faster\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/13-faster.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/13-faster-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/13-faster-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>Notice how the sorting time has further decreased and 22% of if was taken by the TestSorting() function itself. This happens because most of the std::sort() logic was inlined and fine-tuned for this specific\u00a0use case (e.g. it will do the integer comparison in-place instead of\u00a0calling the user-provided callback like qsort() does). You can confirm this by switching to the Disassembly view:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/14-inlined.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4003\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/14-inlined.png\" alt=\"14-inlined\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/14-inlined.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/14-inlined-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/14-inlined-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a><\/li>\n<li>Finally try replacing the vector with a list and check whether the sorting time changes:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/15-list.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-4004\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/15-list.png\" alt=\"15-list\" width=\"1105\" height=\"686\" srcset=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/15-list.png 1105w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/15-list-300x186.png 300w, https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2018\/05\/15-list-1024x636.png 1024w\" sizes=\"(max-width: 1105px) 100vw, 1105px\" \/><\/a>See how the sorting time\u00a0increased as\u00a0updating a linked list involves more memory operations than updating a consecutive array.<\/li>\n<\/ol>\n<p>You can\u00a0turn the profiling on and off\u00a0multiple times during a debug session. Each time you turn it on, VisualGDB will activate the valgrind profiling logic,\u00a0collecting\u00a0the\u00a0detailed\u00a0statistics about the executed code, and each time you turn it off, valgrind will be put into inactive state,\u00a0reducing the slowdown of your application. You can effectively use this technique to profile critical parts of large programs without slowing down the entire program.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to use the Live Profiling\u00a0for Linux programs to analyze the relative performance of the critical\u00a0code without<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[152],"tags":[33,109,153],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3989"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=3989"}],"version-history":[{"count":1,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3989\/revisions"}],"predecessor-version":[{"id":4005,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/3989\/revisions\/4005"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=3989"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=3989"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=3989"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}