Более быстрое завершение кода с помощью 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 выполнить свой процесс, чтобы узнать, где он проводит большую часть своего времени.