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