Я исследую потенциальное ускорение завершения кода при использовании механизма завершения кода clang. Описанный ниже поток - это то, что я нашел в rtags Андерса Баккена.
Единицы перевода анализируются демоном, отслеживающим файлы на предмет изменений. Это делается с помощью вызываемых clang_parseTranslationUnit
и связанных функций ( reparse*
, dispose*
). Когда пользователь запрашивает завершение для данной строки и столбца в исходном файле, демон передает кэшированную единицу перевода для последней сохраненной версии исходного файла и текущего исходного файла в clang_codeCompleteAt
. ( Документы Clang CodeComplete ).
Флаги , передаваемые clang_parseTranslationUnit
(от CompletionThread :: процесса, строка 271 ) являются CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes
. Флаги , передаваемые clang_codeCompleteAt
(от CompletionThread :: процесса, строка 305 ) являются CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns
.
Вызов clang_codeCompleteAt
выполняется очень медленно - для получения завершения требуется около 3-5 секунд даже в тех случаях, когда местом завершения является допустимый код доступа к члену, подмножество предполагаемого варианта использования, упомянутого в документации clang_codeCompleteAt
. Это кажется слишком медленным по стандартам завершения кода IDE. Есть ли способ ускорить это?
CXTranslationUnit_SkipFunctionBodies
,CXCodeComplete_IncludeMacros
,CXCodeComplete_IncludeCodePatterns
и не вижу существенную разницу на кодовом я работаю с. Все они в среднем составляют около 4 секунд на выполнение. Я предполагаю, что это просто из-за размера ЕП.CXTranslationUnit_PrecompiledPreamble
гарантируетreparseTU
очень быстро. Однако даже сCXTranslationUnit_CacheCompletionResults
,clang_codeCompleteAt
мучительно медленно для моего случая использования.Ответы:
Проблема clang_parseTranslationUnit заключается в том, что предварительно скомпилированная преамбула не используется повторно во второй раз, который называется завершением кода. Вычисление преамбулы прекомпиляции занимает более 90% этого времени, поэтому вы должны позволить, чтобы прекомпилированная преамбула была повторно использована как можно скорее.
По умолчанию он повторно используется в третий раз, который вызывается для синтаксического анализа / повторного анализа единицы перевода.
Взгляните на эту переменную PreambleRebuildCounter в ASTUnit.cpp.
Другая проблема заключается в том, что эта преамбула сохраняется во временном файле. Вы можете сохранить предварительно скомпилированную преамбулу в памяти вместо временного файла. Быстрее бы. :)
источник
Иногда задержки такого размера возникают из-за тайм-аутов сетевых ресурсов (общих ресурсов NFS или CIFS на пути поиска файлов или сокетах). Попробуйте отслеживать время выполнения каждого системного вызова, добавив префикс процесса, которым вы запускаете
strace -Tf -o trace.out
. Посмотрите на числа в угловых скобкахtrace.out
для системного вызова, для выполнения которого требуется много времени.Вы также можете отслеживать время между системными вызовами, чтобы увидеть, какая обработка файла занимает слишком много времени. Для этого добавьте префикс к процессу
strace -rf -o trace.out
. Посмотрите на номер перед каждым системным вызовом, чтобы найти длинные интервалы между системными вызовами. Вернитесь назад от этой точки, ищаopen
вызовы, чтобы увидеть, какой файл обрабатывается.Если это не помогает, вы можете профилировать свой процесс, чтобы увидеть, на что он тратит большую часть своего времени.
источник