{"id":3243,"date":"2011-03-29T09:00:00","date_gmt":"2011-03-29T09:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2011\/03\/29\/troubleshooting-tips-for-intellisense-slowness\/"},"modified":"2021-10-05T15:48:23","modified_gmt":"2021-10-05T15:48:23","slug":"troubleshooting-tips-for-intellisense-slowness","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/troubleshooting-tips-for-intellisense-slowness\/","title":{"rendered":"Troubleshooting Tips for IntelliSense Slowness"},"content":{"rendered":"<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/5684.image_thumb_350FC4B0.png\"><img decoding=\"async\" class=\"alignleft size-full wp-image-29271\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/5684.image_thumb_350FC4B0.png\" alt=\"Image 5684 image thumb 350FC4B0\" width=\"79\" height=\"104\" \/><\/a><\/p>\n<p>Hi, my name is <strong>Andy Rich<\/strong> and I\u2019m a QA on the C++ front-end compiler. The IntelliSense system in Visual Studio 2010 comes with far greater power, flexibility, and accuracy, but these improvements come at the cost of greater complexity. The goal of this article is to assist you in troubleshooting this complex system, and give you a peek under the hood at how it works (and what to do when it doesn\u2019t).<\/p>\n<p>&nbsp;<\/p>\n<h4>The problem is usually PCHs<\/h4>\n<p>Having spent a lot of time helping customers with slow IntelliSense, I have found that their performance issues are almost always related to PCH being disabled. For large C++ translation units (and most of the ones that you care about are going to be large), IntelliSense PCH is vital to ensuring fast IntelliSense. Getting your PCH settings right are also vital to having fast builds \u2013 so getting this right can potentially be a boon on two fronts. I have previously written a blog post on the PCH model and how to configure it within the IDE: <a href=\"http:\/\/blogs.msdn.com\/vcblog\/archive\/2010\/01\/26\/precompiled-header-files-in-visual-studio-2010.aspx\" target=\"_blank\" rel=\"noopener\">http:\/\/blogs.msdn.com\/vcblog\/archive\/2010\/01\/26\/precompiled-header-files-in-visual-studio-2010.aspx<\/a>. This blog post will be focused on what to do when you\u2019ve followed those steps and things still aren\u2019t working for you.<\/p>\n<p>&nbsp;<\/p>\n<h4>Start with the error window<\/h4>\n<p>In VS2010 RTM, errors in your PCH will prevent the IntelliSense compiler from creating a PCH. This is something we have addressed in SP1, but even still, the error window can be a good place to start investigating performance issues.<\/p>\n<p>One of the new features in VS2010 is \u201cred squiggles\u201d for C++ &#8211; these diagnostics are provided by the IntelliSense compiler. These same diagnostics are also provided to the error list window. If this window is not visible, you can bring it up using View-&gt;Error List or the hotkey chord \u201cCtrl +\\, E.\u201d In this case, you should be looking explicitly for errors in header files, and starting at the top of the error list window. With VS 2010 RTM, any errors (even ones that the compiler can typically recover from) will prevent your PCH from being built, and cause severe IntelliSense slowness. (This is addressed in SP1, which I discuss in a later section.)<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/7343.image_2D845543.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-29272\" title=\"Start with the error window\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/7343.image_2D845543.png\" alt=\"Start with the error window\" width=\"556\" height=\"117\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/7343.image_2D845543.png 556w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/7343.image_2D845543-300x63.png 300w\" sizes=\"(max-width: 556px) 100vw, 556px\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h4>The IntelliSense compiler is not the build compiler<\/h4>\n<p>It is important, here, to call out that the IntelliSense compiler is different from the build compiler. We have made every effort to give these two compilers parity. (For more information about how this works with C++\/CLI please check this <a href=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2011\/03\/03\/10136696.aspx\" target=\"_blank\" rel=\"noopener\">blog post<\/a>.)<\/p>\n<p>However, there are still differences, and occasionally, a file that compiles without error using our build compiler will not compile properly with our IntelliSense compiler. Often, this is because the IntelliSense compiler has a more strict interpretation of the C++ standard than the build compiler. In these cases, you can usually work around this problem by fixing the error reported by the IntelliSense compiler. (In most cases, the build compiler will happily accept the more-conformant code being required by the IntelliSense compiler.)<\/p>\n<p>Additionally, if you are targeting an architecture other than x86, you may notice that the IntelliSense compiler is always operating in x86 mode. This can produce errors that are very difficult to work around, and while these errors will not prevent you from working with most code, they can cause PCH generation to fail as mentioned above.<\/p>\n<p>If you are unable to find a code workaround for your problems, there is one further stopgap measure that can help: the compiler macro <span style=\"font-family: Courier New;\">__INTELLISENSE__<\/span>, which is only defined when using the IntelliSense compiler. You can use this macro to guard code the IntelliSense compiler does not understand, or use it to toggle between the build and IntelliSense compiler.<\/p>\n<p>&nbsp;<\/p>\n<h4>Context is important<\/h4>\n<p>This is a good opportunity to discuss context in our IntelliSense engine. The IntelliSense engine provides accurate results by always having as correct a view as possible of the source file being compiled. This is fairly straightforward in the case of .cpp files: these are natively compiled and understood by the compiler. However, the situation is less clear for .h files, as these files are compiled only in the context of an associated .cpp file.<\/p>\n<p>In previous releases of Visual C++, header files were only parsed by the IntelliSense parser and included in the NCB once, based on the single context they were compiled in. An <a href=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2007\/12\/18\/intellisense-history-part-1.aspx\" target=\"_blank\" rel=\"noopener\">older post by Jim Springfield<\/a> discusses this so-called \u201cmulti-mod\u201d problem in greater detail. We address this issue in Visual C++ 2010 by having all header files compiled in the context of your current .cpp file, so that this highly contextual information can be more accurate.<\/p>\n<p>However, what is the proper recourse for the IntelliSense engine when an .h file is active in the editor? It cannot compile the .h file by itself \u2013 this would not be the correct context. The .h file is almost certainly included by multiple .cpp files \u2013 which one should be compiled to get the proper context for the .h file?<\/p>\n<p>In Visual C++ 2010, we introduced a bit of technology called the include graph. This allows us to know, for an .h file, all of the .cpp files that have included that .h file, either directly or indirectly. This gives us all of the possible contexts for the .h file, but we still have very little idea which .cpp file is the one you want.<\/p>\n<p>Ideally, this is something that would be configurable by the user, but this seems heavyweight for IntelliSense. What we settled on was looking through your most recently used .cpp files (controlled by the \u201cTU cache\u201d setting in <span style=\"font-family: Courier New;\">Tools-&gt;Options-&gt;Text Editor-&gt;C\/C++-&gt;Advanced<\/span>) and seeing if any of those were reported by the include graph as being a valid context for your .h file. If so, we use that context. If no such context is available, we must fall back on choosing an arbitrary context for the .h file.<\/p>\n<p>&nbsp;<\/p>\n<h4>Verify the PCH is being built<\/h4>\n<p>Let\u2019s get back to diagnosing IntelliSense issues. Assuming your header files are free of IntelliSense errors, we should look into verifying that your PCH is being built. The most foolproof way of accomplishing this is to actually look on your hard drive for the iPCH file to ensure it is being built.<\/p>\n<p>Browse to your solution directory, and find the \u201cipch\u201d directory underneath. In here, you should find one directory per project. And within those directories, the \u201cipch\u201d files themselves. Looking at the timestamps of the files can be informative, but for me, proof positive is to delete the iPCH files (you\u2019ll probably need to shut down your solution first) and ensure the iPCH files are being recreated when IntelliSense is executed on the .cpp file in question.<\/p>\n<p>If you aren\u2019t seeing the iPCH file being generated, this is a good time to go back and review the <a href=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2010\/01\/26\/precompiled-header-files-in-visual-studio-2010.aspx\" target=\"_blank\" rel=\"noopener\">PCH options blog post<\/a> and ensure your settings are really configured correctly.<\/p>\n<p>&nbsp;<\/p>\n<h4>Unless you\u2019re using Makefile projects<\/h4>\n<p>One huge caveat is in the case of makefile projects. By and large, settings in your makefile project are opaque to the Visual Studio project system, and therefore by extension, the IntelliSense system. In these cases, your include directories may not be correct, macro defines may be not set, and any compiler switches you are using in your makefile (including those that control PCH!) will not be on.<\/p>\n<p>For these cases, we have added an extra configuration section to makefile projects. Right-click your project, choose Properties, and go to Configuration Properties-&gt;NMake. The \u201cIntelliSense\u201d subsection in here is for options that are specific to your IntelliSense compiler. These options will be passed ONLY to the IntelliSense compiler, and should be of the same format that you would pass to the build compiler. You should ideally set these according to the same options used in your makefile. In particular, preprocessor definitions, include search path, and forced includes are important to have right. For our purposes, of course, you should also have your PCH options included in the \u201cAdditional Options\u201d section.<\/p>\n<p>As a quick and dirty workaround for PCH, you can often just specify \u201c<span style=\"font-family: Courier New;\">\/Yu<\/span>\u201d with no parameters, and the IntelliSense engine will create a default PCH for you. But in the long run, you will have better overall performance and less issues if you mirror your build system\u2019s PCH settings here.<\/p>\n<p>&nbsp;<\/p>\n<h4>Goto-Definition is a very special case<\/h4>\n<p><strong>Goto-Definition (GTD)<\/strong> is one of the most complicated operations performed by our IntelliSense engine, and one of the most common to suffer IntelliSense slowdown. The big issue with Goto-Definition is that, typically, the definition of the function is not contained in the translation unit currently being parsed. The <i>declaration<\/i> is naturally required by the compiler \u2013 the prototype in your .h file \u2013 but the .cpp file that provides the implementation of this prototype is often not in your current TU; often, it isn\u2019t even in your current project! (And in some cases, it is buried in a static lib or DLL, and no actual code for the definition is possible.)<\/p>\n<p>At a high level, Goto-Definition is implemented like this:<\/p>\n<ol>\n<li>Generate a qualified name for this type (requires a QuickInfo request at the GTD source point).<\/li>\n<li>Search the browse database for all definitions that could match this qualified name.<\/li>\n<li>For each matching definition found, perform a QuickInfo operation to see if the target qualified name matches the source.<\/li>\n<li>If you find a matching definition, stop (don\u2019t keep processing the list).<\/li>\n<li>If you never find a matching definition, show all of the candidates from step 2.<\/li>\n<\/ol>\n<p>The operation that tends to take a long time is step 3. In a previous blog, I discussed how our <a href=\"http:\/\/blogs.msdn.com\/b\/vcblog\/archive\/2010\/01\/26\/precompiled-header-files-in-visual-studio-2010.aspx\" target=\"_blank\" rel=\"noopener\">preparse model can negatively impact performance<\/a>. Step 1 is typically not a problem because we have nearly always already generated a preparse for your current source file. In Step 3, however, we are going to a new, unrelated file; and this file typically does not have a preparse generated. The gating factor on the speed of these operations is the preparse, and the only good way to speed the preparse up is with PCH. So getting your PCH working (as mentioned above) is probably the most important thing you can do for performance.<\/p>\n<p>&nbsp;<\/p>\n<h4>Using Task Manager to pinpoint issues<\/h4>\n<p>Sometimes, it can help to pull up Task Manager, as this will provide some insight into which piece of our complicated IntelliSense\/browsing system is causing the problem. When you perform a long-running Goto-Definition, you can take a look at which process is consuming CPU cycles. If it is devenv.exe, the problem is more likely in the browsing system (a database query, most likely). This is usually due to some kind of complexity of your solution, and is something we\u2019re interested in finding out more about when you encounter it.<\/p>\n<p>If you find that the process eating up resources is <span style=\"font-family: Courier New;\">vcpkgsrv.exe<\/span>, then the problem is in the IntelliSense compiler \u2013 and once again, most likely to be a long-running preparse (which is best solved by having PCH turned on and working).<\/p>\n<p>&nbsp;<\/p>\n<h4>Rich Logging options in Visual C++ 2010<\/h4>\n<p>Visual C++ 2010 has some additional logging options which can help to pinpoint problems. To turn this logging on, go to <span style=\"font-family: Courier New;\">Tools-&gt;Options-&gt;Text Editor-&gt;C\/C++-&gt;Advanced<\/span> and change the options under \u201c<span style=\"font-family: Courier New;\">Diagnostic Logging<\/span>\u201d. To enable full logging of all events (which can be a LOT of logging data), you set Enable Logging to True, Logging Level to 5, and Logging Filter to 255, as in the screenshot below.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/1563.image_662EFF50.png\"><img decoding=\"async\" class=\"size-full wp-image-29270 aligncenter\" title=\"Rich Logging options in Visual C++ 2010\" src=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/1563.image_662EFF50.png\" alt=\"Rich Logging options in Visual C++ 2010\" width=\"493\" height=\"228\" srcset=\"https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/1563.image_662EFF50.png 493w, https:\/\/devblogs.microsoft.com\/cppblog\/wp-content\/uploads\/sites\/9\/2011\/03\/1563.image_662EFF50-300x139.png 300w\" sizes=\"(max-width: 493px) 100vw, 493px\" \/><\/a><\/p>\n<p>You can view the output of this logging in the Output window (you may need to change the \u201cShow output from:\u201d dropdown to \u201cVisual C++ Log\u201d). Briefly, I will go through what the log looks like for a typical QuickInfo operation.<\/p>\n<p>This is the log for a QuickInfo call:<\/p>\n<p><span style=\"font-family: Courier New;\">[WorkItem] &gt;&gt; [eNowQueue] class CQuickInfoWorkItem\n<\/span><span style=\"font-family: Courier New;\">[WorkItem] [eNowQueue] &#8211; Executing class CQuickInfoWorkItem\n<\/span><span style=\"font-family: Courier New;\">[IntelliSense] translation unit: c:\\users\\arich\\documents\\visual studio 2011\\projects\\example_project\\example_project\\example_project.cpp\n<\/span><span style=\"font-family: Courier New;\">[WorkItem] [eNowQueue] &#8211; class CQuickInfoWorkItem (1ms)\n<\/span><span style=\"font-family: Courier New;\">[General] [UI] &#8211; class CQuickInfoWorkItem (1ms)<\/span><\/p>\n<p><span style=\"font-family: Courier New;\">[03\/15\/2011 @ 18:32:22.704] Quick Info : Success : 3 ms : class MyClass<\/span><\/p>\n<p>&nbsp;<\/p>\n<p>The first thing to help understand IntelliSense operations is to note the \u201c&gt;&gt;\u201d character, which indicates the IntelliSense engine has placed an item on the worker queue. For the case of QuickInfo, the work is called \u201c<span style=\"font-family: Courier New;\">CQuickInfoWorkItem<\/span>\u201d. In this scenario, you can see it took 1ms for the QuickInfo workitem to be created and queued, and an additional 3ms for this item to be pulled off the queue, processed, and the result returned. (This was nearly instantaneous because a preparse for this translation unit had already been built.)<\/p>\n<p>The most helpful part of an IntelliSense log is usually looking at the translation unit the IntelliSense compiler has chosen to satisfy your IntelliSense request. If the IntelliSense compiler is loading this TU for the first time, you will also get output that indicates the command-line options this file is being compiled with, which can sometimes be helpful in diagnosing problems, especially the \/Fp parameter (which indicates where the ipch for this file is located).<\/p>\n<p>Note that, in the case of Goto-Definition, because the compiler will probably need to compile multiple translation units in order to provide an answer, you may see multiple \u201cTranslation unit:\u201d info statements for a single operation. (Also, if you have red squiggles on, you will see an additional workitem fired off as a result of navigating to a new source file, in order to check for compilation errors.)<\/p>\n<p>&nbsp;<\/p>\n<h4>Performance Mitigations in Visual Studio 2010 SP1<\/h4>\n<p>We have added three improvements\/mitigations in Visual Studio 2010 SP1 that are designed to provide an improved IntelliSense experience. These are:<\/p>\n<ol>\n<li>Improved database queries resulting in better class view performance<\/li>\n<li>Long-running Goto-Definition operations now have a cancel dialog<\/li>\n<li>IntelliSense PCH will be created even if there are errors in the header<\/li>\n<\/ol>\n<p>Of these improvements, the third should give the most immediate benefit to our users. Previously, we would only create an iPCH file if the PCH header compiled without any errors. In some scenarios (especially with non-x86 code) it was impossible to get the PCH header completely error-free, resulting in very poor IntelliSense performance, as the preparse could not take advantage of PCH speedups. (This was most noticeable during Goto-Definition, when it was more likely that the \u2018target\u2019 TU did not previously have a preparse created.)<\/p>\n<p>With this feature, we have added a few special diagnostics in cases where we were still unable to generate an iPCH. These are mostly the result of project misconfigurations, missing files, and other such catastrophic errors. The text of the error should say something like \u201cAn IntelliSense PCH file was not generated.\u201d If you see these diagnostics in SP1, it is almost certain you will suffer poor IntelliSense performance until the error in the diagnostic is resolved.<\/p>\n<p>&nbsp;<\/p>\n<h4>Getting additional help<\/h4>\n<p>I am always interested in hearing specific feedback about poor IntelliSense performance. My hope is that with the additional diagnostic information provided in this blog post, you can help us pinpoint the performance issues you are having, which component the issues are coming from, and get closer to the actual root cause of the issues. Supplying this additional information (as much as is available) in your connect bug will help us to understand and address these problems.<\/p>\n<p>Thanks!<\/p>\n<p>Andy Rich\nVisual C++ QA<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hi, my name is Andy Rich and I\u2019m a QA on the C++ front-end compiler. The IntelliSense system in Visual Studio 2010 comes with far greater power, flexibility, and accuracy, but these improvements come at the cost of greater complexity. The goal of this article is to assist you in troubleshooting this complex system, and [&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":[65,14,46,66],"class_list":["post-3243","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-cplusplus","tag-compiler","tag-intellisense","tag-ipch","tag-performance"],"acf":[],"blog_post_summary":"<p>Hi, my name is Andy Rich and I\u2019m a QA on the C++ front-end compiler. The IntelliSense system in Visual Studio 2010 comes with far greater power, flexibility, and accuracy, but these improvements come at the cost of greater complexity. The goal of this article is to assist you in troubleshooting this complex system, and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/3243","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=3243"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/3243\/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=3243"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=3243"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=3243"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}