Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Need a guidance to tune the extension usable for large projects with limited resources #7119

Closed
lsmgeb89 opened this issue Mar 6, 2021 · 24 comments
Assignees
Labels
Language Service more info needed The issue report is not actionable in its current state performance

Comments

@lsmgeb89
Copy link

lsmgeb89 commented Mar 6, 2021

Type: LanguageService

Describe the bug

  • OS and Version: Ubuntu 18.04
  • VS Code Version:
    Version: 1.54.1
    Commit: f30a9b73e8ffc278e71575118b6bf568f04587c8
    Date: 2021-03-04T22:38:50.094Z
    Electron: 11.3.0
    Chrome: 87.0.4280.141
    Node.js: 12.18.3
    V8: 8.7.220.31-electron.0
    OS: Linux x64 5.4.0-66-generic
    
  • C/C++ Extension Version: 1.2.2

I have a Ubuntu 18.04 running inside VMware Fusion.
The host is a Macbook Pro which 2.3 GHz Quad-Core Intel Core i5 and 16 GB 2133 MHz LPDDR3.
The virtual machine is assigned 6 cores and 12 GB memory and is just for coding, not for compiling.

Project
The project is large with third-party libraries in a custom toolchain, but targeting regular x86-64 instead of embedded systems.
The legacy building system is CMake and now is based on the Bazel.
Here is the statistics from cloc command.
This statistics doesn't include the library headers in the toolchain.

--------------------------------------------------------------------------------------
Language                             files          blank        comment           code
---------------------------------------------------------------------------------------
C++                                   9501        1186834         854022        6962338
C/C++ Header                          8539         572794         730605        3728608
Protocol Buffers                      1097          55671         102835          89965

The project includes protocol buffer files. In order to make IntelliSense having all the symbols, I usually compile all the .proto files by using CMake.
It will generate a compile_commands.json which includes all the .cc files and .pb.cc files (compiled from .proto).
This compile_commands.json will be fed into the C++ Extension for IntelliSense.
In the root directory of the project, there is a builds directory.
If you compile in the current branch like master, it will generate a directory with config name inside builds directory like build-master-debug.
So if you checkout another branch and then compile it, another directory will be generated inside builds directory.
But another directory build is always soft linked to the build-xxx-yyy directory inside builds for the current branch and config.
Actually, the compile_commands.json is another soft link to the file under build.
Also note that the generated .pb.cc and .pb.h will be in the build-xxx-yyy directory.

Config
Here is my c_cpp_properties.json.

{
    "configurations": [
        {
            "name": "Linux",
            "compileCommands": "${workspaceFolder}/compile_commands.json",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/path/to/toolchain/bin/g++ --sysroot=/path/to/toolchain/toolchain-root",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64"
        }
    ],
    "version": 4
}

Here is part of settings.json which is related to this extension.

"C_Cpp.loggingLevel": "Debug",
"C_Cpp.updateChannel": "Insiders",
"C_Cpp.enhancedColorization": "Disabled",
"C_Cpp.workspaceParsingPriority": "low",
"C_Cpp.intelliSenseMemoryLimit": 8192

Now in this machine, I just use one branch master so that there is only one directory inside builds.
Since I found that if I checkout multiple branches, the extension (or language server) will be busy very frequently if a new branch is checked out.

Steps to reproduce
Once I open the VS Code for this project, the extension (or language server) will take very high CPU and memory very frequently regardless which values I choose for C_Cpp.workspaceParsingPriority and C_Cpp.intelliSenseMemoryLimit.
Usually, when this happened, the whole virtual machine will freeze and nothing can be done.

Back then, I set the C_Cpp.workspaceParsingPriority to high and then I found the system will become freeze finally. But sometimes, it is idle pretty well. Now I just want to find a balanced config which allows me to code in this project and enjoy the convenience of intelliSense and the amount of resource taken is OK and whole system should be responsible all the time. So now I just keep it as low.

For memory, even I set the limitation to 8192 and whole 12 GB and including 2GB swap will be exhausted sometimes. I also tried to set the limitation to 4096 and then I found the GUID of the cpptools-srv would frequently changed. Sometimes, multiple GUIDs will show up in the htop result. I don't know whether that is by design or not. I guess since the memory limitation is reached, it is retrying to kill the old instance and bridge up a new instance. But because of the scope of the project, the memory limitation is reached soon and this pattern repeated.

Expected behavior
Firstly, I want suggestions to make extension usable in my case. Is there any settings could make the language server not work that aggressively? maybe like throttling it only actively some number of files? It's better to make language server running under those kinds of limitation instead of just kill it if the resource it takes exceeds the limitation.

And the extension community should have some guidance or steps to guild all the users to tune the config to make the extension usable for a large project since I see a lot of similar issues here.

And in order to do that, the community should also have some performance numbers showing what kind of project scope needs at least how many resources to make the extension work smoothly. So that users won't waste time to tune it if the system resource is lower than the lower bound.

Plus it's better the extension could expose some statistics to show the status lively like how many files are being analyzed and how many in total, etc. So if some config items are changed, the user could observe this statistics to see whether this extension is working under some expected limitation.

Screenshots
Here is a screenshot of htop.
Screen Shot 2021-03-04 at 10 08 52 PM

@sean-mcmanus sean-mcmanus self-assigned this Mar 8, 2021
@sean-mcmanus sean-mcmanus added Language Service more info needed The issue report is not actionable in its current state labels Mar 8, 2021
@sean-mcmanus
Copy link
Collaborator

What is your CPU/memory usage like when the C_Cpp.intelliSenseEngine is set to "Tag Parser"? If you experience problems with that, then that means there is a problem searching for files or parsing files (the database icon in the status bar should indicate if it's searching for files or parsing). Adding paths to files.exclude can help with tag parsing. The workspaceParsingPriority setting just affects tag parsing of the workspace folder.

Otherwise, it's a problem with IntelliSense or cpptools-srv -- those processes are based on the currently opened TU and has nothing to do with "large projects", just the size of the current TU (source files plus included headers). It's possible you could be hitting a bug with our parser that is causing too much CPU or memory to be used. We may need some sort of repro or sample code in order to investigate further.

@lsmgeb89
Copy link
Author

lsmgeb89 commented Mar 10, 2021

@sean-mcmanus
I've tried Tag Parser. Here is the config.

{
    "configurations": [
        {
            "name": "Linux",
            "compileCommands": "${workspaceFolder}/compile_commands.json",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/path/to/toolchain/bin/g++ --sysroot=/path/to/toolchain/toolchain-root",
            "cStandard": "c11",
            "cppStandard": "c++14",
            "intelliSenseMode": "gcc-x64",
            "browse": {
                "path": [
                    "${workspaceFolder}",
                    "/path/to/toolchain/toolchain-root/usr/include/"
                ],
                "limitSymbolsToIncludedHeaders": true,
            }
        }
    ],
    "version": 4
}
"C_Cpp.loggingLevel": "Debug",
  "C_Cpp.updateChannel": "Insiders",
  "C_Cpp.enhancedColorization": "Disabled",
  "C_Cpp.workspaceParsingPriority": "low",
  "C_Cpp.intelliSenseMemoryLimit": 8192,
  "C_Cpp.intelliSenseEngine": "Tag Parser"

Most of the time, there is no lagging.
The vscode could respond very soon.
Here is a screenshot of htop when it is normal.
Screen Shot 2021-03-08 at 3 25 54 PM

Vscode froze only twice.
Screen Shot 2021-03-08 at 4 26 12 PM
From the result of the htop, the cpptools took a lot of memory.
Here is two screenshots of the htop when vscode froze.
Screen Shot 2021-03-08 at 4 25 10 PM
Screen Shot 2021-03-09 at 6 39 55 PM

So I am guessing that is mostly due to IntelliSense or cpptools-srv.

@sean-mcmanus
Copy link
Collaborator

If intelliSenseEngine is "Tag Parser" and there are no cpptools-srv processes, then the issue can't be due to IntelliSense/cpptools-srv. When you set C_Cpp.loggingLevel to "Debug" what does the output say is happening? Do you get a lot of tag parsing messages? Does the logging stop, as if it's stuck?

@lsmgeb89
Copy link
Author

lsmgeb89 commented Mar 10, 2021

@sean-mcmanus
Yes, I know there is no cpptools-srv.
I mean the problem should be mostly when it is set to IntelliSense mode.

I haven't noticed on the output for the logs.
I will check if it's happening again.
And I noticed that the log in the output window is not auto scrolling.
It's not very convenient.

@sean-mcmanus
Copy link
Collaborator

So you're saying your original issue repros with intelliSenseMode set to "Default"? You mentioned some freezing with intelliSenseMode set to "Tag Parser".

The output window should auto scroll if the cursor is at the bottom.

We have some docs on how to get more info on performance issues at https://github.com/microsoft/vscode-cpptools/wiki/Troubleshooting-Performance-Issues .

If you're seeing cpptools-srv memory usage get too large and having it restart due to the limit, you may be hitting an issue similar to #7085 .

@lsmgeb89
Copy link
Author

Yes, my original issue should reproduce with intelliSenseMode set to "Default".
I did mention some freezing when it is set to "Tag Parser".
But only twice happened in like 10 hours.
So I think that is acceptable.
But back then, I got a freezing every 15 minutes.
So switching back to "Default"?

@sean-mcmanus
Copy link
Collaborator

sean-mcmanus commented Mar 10, 2021

Yeah, then it sounds like our IntelliSense parser in cpptools-srv is hitting some performance issues. We have one known repro at #7085 , which could potentially share the same root cause. Otherwise, we might need some sort of sample repro to investigate further. If you were to generate a preprocessed file via something like g++ -Wp,-v -E -dD -x c++ <other compilerArgs> file.cpp > file.out.cpp that could help identify how large the TU is and possibly what code is causing the issue. If you see error squiggles in the preprocessed file (or via manually navigating the include chain), those could be causing a cascading failure in our parser that could lead to the memory issues.

@lsmgeb89
Copy link
Author

Before I just want to switch to the "Default" mode, I got a freezing in the "Tag Parser" mode.
From log, I see a lot of following entries.
cpptools/fileDeleted: file:///home/xx/workspace/yy/build/zz.cmake.

I guess that's because after I git fetch and git rebase to update my codebase, the symbol link of build directory will be broken.
And then I will fix it by using a command.
So cpptools might think that directory was deleted so that so many events are generated.

@sean-mcmanus
Copy link
Collaborator

You can add /home/xx/workspace/yy/build to your files.exclude setting to avoid that processing.

@lsmgeb89
Copy link
Author

No, I can't exclude that since some symbols are in the generated .pb.cc and .pb.h.
These files are in the build directory.

But I want to exclude the builds directory.
But I want to know if I did that, what will happen?
Since the build directory is soft linked into a sub directory inside the builds.

@sean-mcmanus
Copy link
Collaborator

Adding builds to files.exclude should work, but you'd need to make sure the build directory is still somehow added to the includePath or browse.path so symbols are parsed. Do you hit any issues with that?

@lsmgeb89
Copy link
Author

Does the following config correctly to exclude all the files and directories under the builds directory?

files.exclude": {
  "builds/**": true
}

And this config is put into settings.json instead of c_cpp_properties.json, right?

@sean-mcmanus
Copy link
Collaborator

sean-mcmanus commented Mar 12, 2021

"builds/**" won't work by default and is not recommended because it's a file exclude and folder excludes are better (faster)...you'd have to set C_Cpp.exclusionPolicy to checkFilesAndFolders (if you really wanted file exclusions). Can you use "**/builds" ("builds" would work if it's at the root of your workspace folder)?

It goes in settings.json (or the settings section of your workspace file).

@lsmgeb89
Copy link
Author

OK. Updated the config to **/builds.

@lsmgeb89
Copy link
Author

In the "Tag Parser" mode with above config change, vscode is very smooth.
Change the config to default mode to reproduce the issue.

@lsmgeb89
Copy link
Author

There is a crash from cpptools-srv around 6:04 PM once I switched to default mode.

ls /var/crash/
-rw-r----- 1 xxx whoopsie 104M Mar 15 18:04 _home_xxx_.vscode_extensions_ms-vscode.cpptools-1.2.2_bin_cpptools-srv.1000.crash

In the log, I see 6 logs like Shutting down IntelliSense server: some_file_in_workspace.cc.
But since there is no timestamp in the log, I can't know whether it is related to the crash.

@sean-mcmanus
Copy link
Collaborator

Do you see a "crashed" message in the logging? I assume not, which would imply you're hitting a crash on shutdown such as #7161 . If the crash is happening when the process is shutting down, there shouldn't be any negative effect, other than crash dumps being created if your system is configured to do that.

@lsmgeb89
Copy link
Author

lsmgeb89 commented Mar 16, 2021

There is no "crashed" message in the logging.

But now I see all 11G memory + 2G swap has been exhausted and there are 3 GUIDs of cpptools-srv in the htop.
And vscode UI becomes lagging and unresponsive.
Is that normal?

@sean-mcmanus
Copy link
Collaborator

That doesn't sound normal. There is one known case of this at #7085 which we have a fix for our next release. Attaching a debugger to cpptools-srv to get a call stack (https://github.com/microsoft/vscode-cpptools/wiki/Attaching-debugger-to-cpptools-or-cpptools%E2%80%90srv) or getting perf logs (https://github.com/microsoft/vscode-cpptools/wiki/Troubleshooting-Performance-Issues) could determine what the cause is and if it's the same or not.

@lsmgeb89
Copy link
Author

Here is the call stack of the core dump. It looks like the same issue as #7161.

xxx@dev:/var/crash/cpp$ gdb `cat ExecutablePath` CoreDump
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /home/xxx/.vscode/extensions/ms-vscode.cpptools-1.2.2/bin/cpptools-srv...
[New LWP 123162]
[New LWP 123160]
[New LWP 123154]
[New LWP 123158]
[New LWP 123165]
[New LWP 123157]
[New LWP 123159]
[New LWP 123156]
[New LWP 123155]
[New LWP 123161]
[New LWP 123164]
[New LWP 123166]
[New LWP 123163]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `/home/xxx/.vscode/extensions/ms-vscode.cpptools-1.2.2/bin/cpptools-srv 120'.
Program terminated with signal SIGABRT, Aborted.
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
50	../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
[Current thread is 1 (Thread 0x7fbf39b7e700 (LWP 123162))]
(gdb) bt
#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
#1  0x00007fbf3d3dc859 in __GI_abort () at abort.c:79
#2  0x0000000000565323 in __gnu_cxx::__verbose_terminate_handler() [clone .cold] ()
#3  0x0000000000a642d6 in __cxxabiv1::__terminate(void (*)()) ()
#4  0x0000000000a64341 in std::terminate() ()
#5  0x00000000005de2ce in std::thread::~thread() ()
#6  0x0000000000a0aa82 in msvc::channel_manager_t::~channel_manager_t() ()
#7  0x0000000000a096a0 in msvc::pipe_channel_t::~pipe_channel_t() ()
#8  0x0000000000a0e094 in msvc::pipe_channel_t::queue_call(msvc::common_channel_t::async_call_context_t*)::$_1::__invoke(uv_work_s*, int) ()
#9  0x0000000000a4f288 in uv.work_done ()
#10 0x0000000000a51d14 in uv.async_io ()
#11 0x0000000000a53e65 in uv.io_poll ()
#12 0x0000000000a52178 in uv_run ()
#13 0x0000000000a0ae1e in msvc::channel_manager_t::thread_proc() ()
#14 0x0000000000ae5010 in execute_native_thread_routine ()
#15 0x00007fbf3d5b2609 in start_thread (arg=<optimized out>) at pthread_create.c:477
#16 0x00007fbf3d4d9293 in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:95
(gdb) 

@sean-mcmanus
Copy link
Collaborator

Yes, thanks for confirming. Also, we don't currently believe that core dump is related to the other memory usage issue you're seeing, although it's possible under high memory usage conditions you could be seeing the IntelliSense process shutdown (intentionally) and restart due to hitting the C_Cpp.intelliSenseMemoryLimit.

@lsmgeb89
Copy link
Author

For the performance issue, it's kind of easy to reproduce it.
I just close all the files and restart the vscode and then open two .cc files: one with 1675 lines and another with 589 lines.
The 11G memory and 2G swap will be gone.
There are 28 cpptools-srv process in the htop.
I don't know which one to perf it.
And there is no "Process ID" in the log.
But after some time, the memory will decrease to 9G and swap to 1G and number of process of cpptools-srv is 14.

@sean-mcmanus
Copy link
Collaborator

sean-mcmanus commented Mar 17, 2021

Only 1 cpptools-srv is supposed to exist per TU (open source file) up to a per-core max. Running Find All References will also temporarily create them. If you have 28 existing, you may want to kill them or restart your machine if you want to identify which process to get perf data from -- however my guess is that you're actually seeing threads and not processes (so 14-28 threads would be normal). Also, can you try your repro with opening just one of the files? The files should be independent and spawn separate cpptools-srv, so opening 2 files is unlikely to be necessary.

FYI, the size of the particular files can be deceivingly small, because it may include project and system headers which can increase the size to hundreds of thousands of lines of code. You can run a command like <compilerName> -Wp,-v -E <compilerArgs> > test.out.cpp to view the preprocessed TU, which can also be useful for identifying potential issues in the headers that could break our IntelliSense parsing.

@github-actions
Copy link

This issue has been closed automatically because it needs more information and has not had recent activity.

@github-actions github-actions bot locked and limited conversation to collaborators Jul 1, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Language Service more info needed The issue report is not actionable in its current state performance
Projects
None yet
Development

No branches or pull requests

2 participants