我正在研究使用clang的代码完成机制时潜在的代码完成速度。下面描述的流程是我在rtags中由Anders Bakken发现的。
翻译单元由守护程序监视文件进行解析以进行更改。这是通过调用clang_parseTranslationUnit
和相关函数(reparse*
,dispose*
)来完成的。当用户在源文件中的给定行和列请求完成时,守护程序将源文件的上次保存版本和当前源文件的高速缓存转换单元传递给clang_codeCompleteAt
。 (Clang CodeComplete docs)。
传递给clang_parseTranslationUnit
(来自CompletionThread::process, line 271)的标记为CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes
。传递给clang_codeCompleteAt
(来自CompletionThread::process, line 305)的标记为CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns
。
对clang_codeCompleteAt
的调用非常慢 - 即使在完成位置是合法成员访问代码的情况下,获取完成也需要大约3-5秒,这是在上面提到的预期用例的子集clang_codeCompleteAt
的文件。 IDE代码完成标准似乎太慢了。有没有办法加速这个?
答案 0 :(得分:6)
clang_parseTranslationUnit的问题是第二次被称为代码完成时不会重用预编译的前导码。计算预编译前导码需要超过这些时间的90%,因此您应该允许尽可能快地重用预编译的前导码。
默认情况下,第三次调用它来解析/重新分析翻译单元。
看看这个变量' PreambleRebuildCounter'在ASTUnit.cpp。
其他问题是此序言保存在临时文件中。您可以将预编译的前导码保留在内存中而不是临时文件中。它会更快。 :)
答案 1 :(得分:4)
有时这种程度的延迟是由于网络资源超时(文件搜索路径或套接字上的NFS或CIFS共享)。尝试通过使用strace -Tf -o trace.out
为您的运行添加前缀来监控每个系统调用完成所需的时间。对于需要很长时间才能完成的系统调用,请查看trace.out
中尖括号中的数字。
您还可以监视系统调用之间的时间,以查看文件的哪个处理需要很长时间才能完成。为此,请使用strace -rf -o trace.out
为您的流程添加前缀。查看每次系统调用之前的数字,以查找较长的系统调用间隔。从那一点开始寻找open
次调用,看看哪个是正在处理的文件。
如果这没有帮助,您可以profile您的流程查看其大部分时间花在哪里。