使用 clang 更快地完成代码

我正在研究使用 clang 的代码完成机制时潜在的代码完成加速。下面描述的流程是我在 AndersBakken 的 标签中发现的。

翻译单元由守护进程监视文件解析以进行更改。这是由所谓的 clang_parseTranslationUnit和相关函数(reparse*dispose*)完成的。当用户在源文件的给定行和列请求完成时,守护进程将源文件的最后一个保存版本和当前源文件的缓存翻译单元传递给 clang_codeCompleteAt。(Clang CodeComplete 文档).

传递给 clang_parseTranslationUnit(来自 Process,第271行)的标志是 CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes。传递给 clang_codeCompleteAt(来自 Process,第305行)的标志是 CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns

clang_codeCompleteAt的调用非常慢——即使在完成位置是合法的成员访问代码(clang_codeCompleteAt文档中提到的预期用例的子集)的情况下,也需要大约3-5秒才能完成。按照 IDE 代码完成标准,这似乎太慢了。有什么办法能加快进度吗?

5499 次浏览

Sometimes delays of this magnitude are due to timeouts on network resources (NFS or CIFS shares on a file search path or sockets). Try monitoring the time each system call takes to complete by prefixing the process your run with strace -Tf -o trace.out. Look at the numbers in angle brackets in trace.out for the system call that takes a long time to complete.

You can also monitor the time between system calls to see which processing of a file takes too long to complete. To do this, prefix the process your run with strace -rf -o trace.out. Look at the number before each system call to look for long system call intervals. Go backwards from that point looking for open calls to see which was the file that was being processed.

If this doesn't help, you can profile your process to see where it spends most of its time.

The problem that clang_parseTranslationUnit has is that precompiled preamble is not reused the second time that is called code completion. Calculate the precompile preamble takes more than the 90% of these time so you should allow that the precompiled preamble was reused as soon as posible.

By default it is reused the third time that is called to parse/reparse translation unit.

Take a look of this variable 'PreambleRebuildCounter' in ASTUnit.cpp.

Other problem is that this preamble is saved in a temporary file. You can keep the precompiled preamble in memory instead of a temporary file. It would be faster. :)