{"id":4273,"date":"2009-09-10T12:12:00","date_gmt":"2009-09-10T12:12:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2009\/09\/10\/linker-throughput\/"},"modified":"2019-02-18T18:45:47","modified_gmt":"2019-02-18T18:45:47","slug":"linker-throughput","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/linker-throughput\/","title":{"rendered":"Linker throughput"},"content":{"rendered":"<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Hello, my name is Chandler Shen, a developer from the Visual C++ Shanghai team.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">We have made some changes in the upcoming Visual C++ 2010 release to improve the performance of linker. I would like to first give a brief overview of the linker and how we analyze the bottlenecks of current implementation. Later, I will describe the changes we made and the impact on linker performance.<\/font><\/p>\n<h2><span><font size=\"5\"><font color=\"#365f91\"><font face=\"Cambria\">Our Focus<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\"><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">We were targeting the linker throughput of large scale projects full build scenario because this scenario matters most in linker throughput scalability. Incremental linking and smaller projects will not benefit from the work I describe in this blog.<\/font><\/p>\n<h2><span><font size=\"5\"><font color=\"#365f91\"><font face=\"Cambria\">Brief Overview of Linker<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\"><\/font>&nbsp;<\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Traditionally, what&rsquo;s done by linker can be split into two phases: <\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">1.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Pass1: collecting definitions of symbols (from both object files and libraries)<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font face=\"Calibri\" size=\"3\">2.<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Pass2: fixing up references to symbols with final address (actually Relative Virtual Address) and writing out the final image.<\/font><\/p>\n<h2><span><font size=\"4\"><font color=\"#4f81bd\"><font face=\"Cambria\">Link Time Code Generation (LTCG)<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">If <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/0zza0de8(VS.100).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">\/GL (Whole Program Optimization)<\/font><\/a><font face=\"Calibri\" size=\"3\"> is specified when compiling, the compiler will generate a special format of object file containing intermediate language. When linker encounters such object files, Pass1 becomes a 2-phase procedure. From these object files, the linker first calls into compiler to collect definitions of all public symbols to build a complete public symbol table. Then the linker supplies this symbol table to the compiler which generates the final machine instructions (or code generation). <\/font><\/p>\n<h2><span><font size=\"4\"><font color=\"#4f81bd\"><font face=\"Cambria\">Debug Information<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">During Pass2, in addition to writing the final image, linker will also write debug information into a PDB (Program Database) file if user specifies <\/font><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/xe4t6fc1(VS.100).aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">\/DEBUG (Generate Debug Info)<\/font><\/a><font face=\"Calibri\" size=\"3\">. Some of this debug information, such as address of symbols, is not decided until linking.<\/font><\/p>\n<h2><span><font size=\"5\"><font color=\"#365f91\"><font face=\"Cambria\">Bottlenecks<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">In this section, I will show how we analyze some test cases to figure out bottlenecks of performance.<\/font><\/p>\n<h2><span><font size=\"4\"><font color=\"#4f81bd\"><font face=\"Cambria\">Test Cases<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">To get an objective conclusion, four real world projects (whose names are omitted) differ in scale, including proj1, proj2, proj3 and proj4, were chosen as test cases.<\/font><\/p>\n<p class=\"MsoCaption\"><a class=\"\" title=\"_Ref236545545\" name=\"_Ref236545545\"><\/a><strong><font face=\"Calibri\" color=\"#4f81bd\">Table <\/font><\/strong><strong><font face=\"Calibri\" color=\"#4f81bd\">1 Measurements of test cases<\/font><\/strong><\/p>\n<table class=\"MsoNormalTable\" cellspacing=\"0\" cellpadding=\"0\" width=\"373\" border=\"0\">\n<tbody>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"103\" colspan=\"2\">\n<p class=\"Textintable\"><strong><font size=\"3\"><font face=\"Calibri\">&nbsp;<\/p>\n<p><\/font><\/font><\/strong><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"68\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Proj1<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" width=\"71\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Proj2<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"72\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Proj3<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"60\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Proj4<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" nowrap width=\"48\" rowspan=\"3\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Files<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"55\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Total<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" width=\"68\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">55<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"71\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">27<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"72\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">168<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"60\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1066<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"55\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">.obj<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" width=\"68\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">4<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"71\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">6<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"72\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">7<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"60\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">882<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"55\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">.lib<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" width=\"68\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">51<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"71\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">21<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"72\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">161<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"60\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">184<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"103\" colspan=\"2\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Symbols<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"68\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">6026<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" width=\"71\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">22436<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"72\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">69570<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"60\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">110262<\/font><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><font face=\"Calibri\" size=\"3\">In Table 1, the number of &ldquo;symbols&rdquo; is the number of entries of the symbol table which is internally used by linker to store the information of all external symbols. It is noticeable that &ldquo;proj4&rdquo; is much bigger than others. <\/font><\/p>\n<h2><span><font size=\"4\"><font color=\"#4f81bd\"><font face=\"Cambria\">Test Environment<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Following is the configuration of the test machine<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">&middot;<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Hardware<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">o<\/font><span>&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">CPU&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Intel Xeon CPU 3.20GHz, 4 cores<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">o<\/font><span>&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">RAM&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2G<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">&middot;<\/font><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Software&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Windows Vista 32-bit<\/font><\/p>\n<h2><span><font size=\"4\"><font color=\"#4f81bd\"><font face=\"Cambria\">Results<\/p>\n<p><\/font><\/font><\/font><\/span><\/h2>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">To minimize the effect of environment, all cases were run for five times. And the unit of time is in seconds.<\/font><\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">In Table 2 and Table 3, it showed that for each test case, there is always one (usually the first, marked in <span>red<\/span>) run which takes much longer than others.&nbsp; While one run (marked in <span>Green<\/span>) may take a much shorter run. This is because following two reasons<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">l<\/font><span>&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">OS will cache a file&rsquo;s content in memory for next read (called prefetch on Windows XP, and <\/font><a href=\"http:\/\/www.microsoft.com\/windows\/windows-vista\/features\/superfetch.aspx\"><font face=\"Calibri\" color=\"#0000ff\" size=\"3\">SuperFetch<\/font><\/a><font face=\"Calibri\" size=\"3\"> on Windows Vista)<\/font><\/p>\n<p class=\"MsoListParagraph\"><span><span><font size=\"3\">l<\/font><span>&nbsp; <\/span><\/span><\/span><font face=\"Calibri\" size=\"3\">Most of modern hard disks will cache a file&rsquo;s content for next read<\/font><\/p>\n<p class=\"MsoNormal\">\n<p><font face=\"Calibri\" size=\"3\">&nbsp;<\/font><\/p>\n<\/p>\n<p class=\"MsoNormal\"><font face=\"Calibri\" size=\"3\">Comparing Table 2 with Table 3, we can notice that if \/debug is off, the time of Pass2 is much shorter. So it indicates that the majority of Pass2 is writing PDB files<\/font><\/p>\n<p class=\"MsoCaption\"><a class=\"\" title=\"_Ref236553801\" name=\"_Ref236553801\"><\/a><strong><font face=\"Calibri\" color=\"#4f81bd\">Table <\/font><\/strong><strong><font face=\"Calibri\" color=\"#4f81bd\">2 Test result of Non-LTCG with \/Debug On<\/font><\/strong><\/p>\n<table class=\"MsoNormalTable\" cellspacing=\"0\" cellpadding=\"0\" width=\"299\" border=\"0\">\n<thead>\n<tr>\n<td class=\"\" width=\"103\" colspan=\"2\"><strong><font face=\"Calibri\" color=\"#4f81bd\"><\/font><\/strong><\/td>\n<td class=\"\" valign=\"bottom\" width=\"57\">\n<p class=\"Textintable\"><strong><font size=\"3\"><font face=\"Calibri\">Pass1<\/p>\n<p><\/font><\/font><\/strong><\/p>\n<\/td>\n<td class=\"\" nowrap width=\"64\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Pass2<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" nowrap width=\"75\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Total<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td class=\"\" nowrap width=\"81\" rowspan=\"5\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">Proj1<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"22\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">1<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"57\">\n<p class=\"Textintable\"><b><span><font size=\"3\"><font face=\"Calibri\">4.437<\/p>\n<p><\/font><\/font><\/span><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"64\">\n<p class=\"Textintable\"><b><span><font size=\"3\"><font face=\"Calibri\">2.328<\/p>\n<p><\/font><\/font><\/span><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"75\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">6.765<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"22\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">2<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"57\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">0.266<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"64\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.218<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"75\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.484<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"22\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">3<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"57\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">0.265<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"64\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.188<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"75\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.453<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"22\">\n<p class=\"Textintable\"><b><font size=\"3\"><font face=\"Calibri\">4<\/p>\n<p><\/font><\/font><\/b><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"57\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">0.265<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"64\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.219<\/font><\/p>\n<\/td>\n<td class=\"\" valign=\"bottom\" nowrap width=\"75\">\n<p class=\"Textintable\"><font face=\"Calibri\" size=\"3\">1.484<\/font><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td class=\"\" valign=\"bottom\" nowrap width=\"22\">\n<p class=\"Textintable\" style=\"LINE-HEI\">\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Hello, my name is Chandler Shen, a developer from the Visual C++ Shanghai team. We have made some changes in the upcoming Visual C++ 2010 release to improve the performance of linker. I would like to first give a brief overview of the linker and how we analyze the bottlenecks of current implementation. Later, I [&hellip;]<\/p>\n","protected":false},"author":289,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[19,25],"class_list":["post-4273","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","tag-link-time-code-generation","tag-linker"],"acf":[],"blog_post_summary":"<p>Hello, my name is Chandler Shen, a developer from the Visual C++ Shanghai team. We have made some changes in the upcoming Visual C++ 2010 release to improve the performance of linker. I would like to first give a brief overview of the linker and how we analyze the bottlenecks of current implementation. Later, I [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4273","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/289"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=4273"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/4273\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=4273"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=4273"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=4273"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}