Repository navigation
excessive memory usage in IntelliSense with MSVC non-conforming preprocessor (OpenUSD/Pixar) #13205
Copy link
Copy link
Closed
Closed
Bug
Copy link
Description
Environment
- OS and Version: Windows 11 10.0.26100 x64
- VS Code Version: 1.96.4 commit cd4ee3b1c348a
- C/C++ Extension Version: 1.22.11 (ms-vscode.cpptools); 1.3.0 (ms-vscode.cpptools-extension-pack)
- If using SSH remote, specify OS of remote machine:
Bug Summary and Steps to Reproduce
Bug Summary:
On a very large C++ codebase, cpptools-srv.exe will consume memory, starving out the rest of the system:
I have C_Cpp: Max Memory set, but it does not appear to be used:
Steps to reproduce:
- Open a very large C++ directory, potentially multiple in multiple instances of VSCode
- Wait
- Observe cpptools-srv.exe processes consuming significant amounts of memory
Expected behavior:
- Max memory limit is enforced
Configuration and Logs
{
"configurations": [
{
"name": "Win32",
"intelliSenseMode": "msvc-x64",
"cStandard": "c11",
"cppStandard": "c++17",
"compileCommands": "${workspaceFolder}/_build/windows-x86_64/release/compile_commands-full.json",
"includePath": [
"${default}",
"${workspaceFolder}/include"
]
},
],
"version": 4
}
-------- Diagnostics - 1/27/2025, 5:55:42 PM
Version: 1.22.11
Current Configuration:
{
"name": "Win32",
"includePath": [
"c:/src/<redacted>/**"
],
"defines": [
"_DEBUG",
"UNICODE",
"_UNICODE"
],
"windowsSdkVersion": "10.0.22621.0",
"compilerPath": "cl.exe",
"cStandard": "c17",
"cppStandard": "c++17",
"intelliSenseMode": "windows-msvc-x64",
"compilerPathInCppPropertiesJson": "cl.exe",
"intelliSenseModeIsExplicit": false,
"cStandardIsExplicit": false,
"cppStandardIsExplicit": false,
"mergeConfigurations": false,
"compilerPathIsExplicit": false,
"browse": {
"path": [
"c:/src/kit/**",
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
}
}
Modified Settings:
{
"C_Cpp.maxMemory": 4000
}
Additional Tracked Settings:
{
"editorTabSize": 4,
"editorInsertSpaces": true,
"editorAutoClosingBrackets": "languageDefined",
"filesEncoding": "utf8",
"filesAssociations": {},
"filesExclude": {
"**/.git": true,
"**/.svn": true,
"**/.hg": true,
"**/CVS": true,
"**/.DS_Store": true,
"**/Thumbs.db": true
},
"filesAutoSaveAfterDelay": false,
"editorInlayHintsEnabled": true,
"editorParameterHintsEnabled": true,
"searchExclude": {
"**/node_modules": true,
"**/bower_components": true,
"**/*.code-search": true
},
"workbenchSettingsEditor": "ui"
}
cpptools version (native): 1.22.11.0
Current database path: C:\USERS\REDACTED\APPDATA\LOCAL\MICROSOFT\VSCODE-CPPTOOLS\D04989D4087A51DA9667FC71DEFAB4CC\.BROWSE.VC.DB
No active translation units.
------- Workspace parsing diagnostics -------
Number of files discovered (not excluded): 155248
Number of files parsed: 30183Other Extensions
No response
Additional context
No response
Reactions are currently unavailable


Activity
sean-mcmanus commentedon Jan 28, 2025
The settings are behaving as expected -- they don't limit the memory usage of a single cpptools-srv process.
When you run the C/C++: Log Diagnostics command after opening a source file -- what memory usage is reported per TU? Over 15 GB? If so, that seems like it might be a bug. Your logging indicates no active files have been started.
The cpptools-srv process only has memory for the current TU (source file and headers), so having a "large code base" should not make a difference.
sean-mcmanus commentedon Jan 28, 2025
Josh Kriegshauser (@jkriegshauser) Also, your repro steps don't indicate that you have opened any files? No cpptools-srv process should launch if you don't open any files.
jkriegshauser commentedon Jan 28, 2025
Oh, I didn't realize it was per TU. I opened one VSCode instance with two source windows open. I have several source files open in the left source window and only one in the right source window. Active, the left source file is a .cpp file with 10,978 lines and in the right, a .cpp file with 1,028 lines.
I have 3 cpptools-srv.exe processes running each consuming nearly 15 GB of RAM each:
Though every time I do
C/C++: Log Diagnosticsit saysNo active translation units.I even bound it to a key and execute the key with the larger source file active and get the same message:sean-mcmanus commentedon Jan 29, 2025
Josh Kriegshauser (@jkriegshauser) Those might be dangling processes. Can you kill them? Does your C/C++ logging with C_Cpp.loggingLevel set to "Debug" indicate the IntelliSense process is shutting down or crashing?
jkriegshauser commentedon Jan 29, 2025
I had 13 cpptools-srv processes running, the most using ~26 GB RAM. I killed them all with
taskkilland 5 restarted. I see some debug logging happening now after opening it. When I killed the processes I saw this appear in the logs:sean-mcmanus commentedon Jan 29, 2025
Josh Kriegshauser (@jkriegshauser) Are the crash logging from your killing the processes or from the processes actually crashing? If it's an actual crash you could potentially get a crash call stack via attaching a debugger before it crashes (https://github.com/microsoft/vscode-cpptools/wiki/Attaching-debugger-to-cpptools-or-cpptools%E2%80%90srv). It sounds like our IntelliSense parser may be hitting some bug while processing your TU. If it's using CPU while memory is increasing, attaching a debugger and hitting a breakpoint might show what processing is causing the issue if it's stuck in some loop that is allocating memory.
jkriegshauser commentedon Jan 29, 2025
I think those were from me killing the process. I have some huge memory processes:
I used procdump to get mini-dumps of them and the biggest ones have threads doing this:
Unfortunately the symbols are minimal so I don't see any local variables or anything. But it definitely looks like there's some recursion happening. Would be nice to know what macro is kicking it off
sean-mcmanus commentedon Jan 29, 2025
Josh Kriegshauser (@jkriegshauser) I've sent an email to the team involved. Are you able to reduce the TU to locate the macro that is triggering the excessive/infinite recursion?
jkriegshauser commentedon Jan 29, 2025
Sean McManus (@sean-mcmanus) not easily. I'm not even sure which file it's parsing. I looked at strings in the minidump that I gathered and didn't see any
.objor.cppfiles, but several headers. Having PDB files with local variables might help. This tool isn't open-source I take it?bobbrow commentedon Feb 25, 2025
No, the tool is not open source and we don't release binaries with full symbols. I looked at the stack and the place in the parser where I see a potential for recursion appears to be related to clang's
__is_identifierand__has_warningmacros though it could still be something else. It's possible a search through your workspace folder may turn up some usage of these macros that is not handled correctly by the parser which results in this infinite or extremely inefficient recursion. Our enforcement of process memory usage only happens after each IntelliSense operation completes and it appears that this one never completes to give us the opportunity to trim it.To reproduce this, I would recommend only opening one cpp file at a time and watching Task Manager for a runaway process. The stack indicates that the recursion is happening during process initialization (the first parse through the code), so you shouldn't need to interact with the file, just watch for runaway memory consumption. Once you have identified a translation unit that reproduces this, you can delete content from it until it gets into a state where it does not eat up an unreasonable amount of memory (e.g. the 266MB process in your screenshot). When it stops reproducing, you'll want to revert your last edit because the code you just deleted appears to be important for the repro. You will need to terminate the runaway process after each edit so that the extension can try parsing it again. When you terminate a runaway process, you will need to interact with the file at least once (hover, type, etc) so that the extension can detect that the process "crashed" and can respawn it.
Some strategies for edits that work when doing this include:
#includes#includesRepeat these steps until you have something small or safe enough to share with us (e.g. no proprietary code) and we can take over from there.
jkriegshauser commentedon Feb 25, 2025
Thanks Bob Brown (@bobbrow), I'll see if I can carve out some time to do so. I have a sneaking suspicion that it has something to do with OpenUSD (we're using Tag v24.05) include files, since when I wrap those includes with
#ifndef __INTELLISENSE__the problem corrects itself, though I don't get any intellisense on USD includes (of course, with intellisense not completing I get nothing).I opened a .cpp file that includes at least the following OpenUSD includes:
and it's up to 4.5GB so far with a peak of 8.8GB with no intellisense help to support thus far
bobbrow commentedon Mar 5, 2025
Our IntelliSense team was talking about an issue with these Pixar headers in Visual Studio today and I learned that there is also a Developer Community ticket or two covering this issue. They haven't reduced it down to a specific macro or macros yet, but my understanding is that there are some particularly deep macro expansions going on in this codebase (which matches the stack you sent earlier). I had thought that maybe this was a case of an infinite loop, but it appears to be worse than that unfortunately.
I suspected
pxr/base/tf/preprocessorUtilsLite.hgiven some of the deep recursion in those definitions, but openingpreprocessorUtilsLite.cppdoesn't suffer from this issue. I'll keep trying to help them find a root cause as I find time.jkriegshauser commentedon Mar 5, 2025
Bob Brown (@bobbrow) thanks for the update. I haven't had a chance to try to whittle it down either given that it's a very time-consuming process 😞
bobbrow commentedon Mar 5, 2025
I understand. If you do have time, we'll accept the help. But I also think we might have enough to go on at this point. I can reproduce a significant (but temporary) memory increase just pasting that list of headers into an empty source file and that might be enough.
bobbrow commentedon Mar 7, 2025
Hi Josh Kriegshauser (@jkriegshauser),
I have some good news to share. We discovered that the Pixar headers support both MSVC's conforming and non-conforming preprocessors. When you configure your project and IntelliSense to use the newer standards conforming preprocessor, these headers do not require the deep recursion and memory usage in the IntelliSense process.
Can you try adding this into your configurations in
c_cpp_properties.jsonand let me know if that addresses the issue?This will instruct IntelliSense to emulate MSVC's standards conforming preprocessor which will take the faster path to compile the sources.
EDIT: for reference, this is the path we want to trigger: https://github.com/PixarAnimationStudios/OpenUSD/blob/1ff329aac66e0cab154cb9217f5d70c12e21f712/pxr/base/arch/defines.h#L93-L103
jkriegshauser commentedon Mar 7, 2025
Awesome! That definitely seems to help!
I can actually use Intellisense in files that include Pixar headers now! 🎉
[-]cpptools-srv using too much memory[/-][+]excessive memory usage in IntelliSense with MSVC non-conforming preprocessor (OpenUSD/Pixar)[/+]bobbrow commentedon Mar 7, 2025
That's great to hear. I'm going to close this issue as mitigated and write a Q&A topic for it. The issue with the non-conforming preprocessor mode will be tracked by the Visual Studio C++ team.
nv-scristiano commentedon Mar 18, 2025
the offending macro is at
include\pxr\base\tf\staticTokens.hAnother temporary workaround for the issue is changing it to :