Estou investigando possíveis acelerações de conclusão de código ao usar o mecanismo de conclusão de código do clang. O fluxo descrito abaixo é o que encontrei no rtags , de Anders Bakken.
As unidades de tradução são analisadas por um daemon que monitora arquivos para alterações. Isso é feito por clang_parseTranslationUnit
funções chamadas e relacionadas ( reparse*
, dispose*
). Quando o usuário solicita o preenchimento de uma determinada linha e coluna em um arquivo de origem, o daemon passa a unidade de tradução em cache da última versão salva do arquivo de origem e do arquivo de origem atual para clang_codeCompleteAt
. ( Documentos do Clang CodeComplete ).
Os sinalizadores passados para clang_parseTranslationUnit
(de CompletionThread :: process, linha 271 ) são CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes
. Os sinalizadores passados para clang_codeCompleteAt
(de CompletionThread :: process, linha 305 ) são CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns
.
A chamada para clang_codeCompleteAt
é muito lenta - leva cerca de 3-5 segundos para obter uma conclusão, mesmo nos casos em que o local de conclusão é um código de acesso de membro legítimo, um subconjunto do caso de uso pretendido mencionado na documentação de clang_codeCompleteAt
. Isso parece muito lento para os padrões de conclusão de código IDE. Existe uma maneira de acelerar isso?
CXTranslationUnit_SkipFunctionBodies
,CXCodeComplete_IncludeMacros
,CXCodeComplete_IncludeCodePatterns
e não viu uma diferença significativa na base de código que eu estou trabalhando. Todos eles em média cerca de 4 segundos por completo. Acho que isso se deve ao tamanho das TUs.CXTranslationUnit_PrecompiledPreamble
garantereparseTU
é muito rápido. No entanto, mesmo comCXTranslationUnit_CacheCompletionResults
,clang_codeCompleteAt
é dolorosamente lento para meu caso de uso.Respostas:
O problema que clang_parseTranslationUnit tem é que o preâmbulo pré-compilado não é reutilizado na segunda vez que é chamado de conclusão de código. Calcular o preâmbulo pré-compilado leva mais de 90% desse tempo, portanto, você deve permitir que o preâmbulo pré-compilado seja reutilizado assim que possível.
Por padrão, ele é reutilizado pela terceira vez que é chamado para analisar / reanalisar a unidade de tradução.
Dê uma olhada na variável 'PreambleRebuildCounter' em ASTUnit.cpp.
Outro problema é que este preâmbulo é salvo em um arquivo temporário. Você pode manter o preâmbulo pré-compilado na memória, em vez de em um arquivo temporário. Seria mais rápido. :)
fonte
Às vezes, atrasos dessa magnitude são devido a tempos limite nos recursos de rede (compartilhamentos NFS ou CIFS em um caminho de pesquisa de arquivo ou soquetes). Tente monitorar o tempo que cada chamada de sistema leva para ser concluída, prefixando o processo com o qual sua execução
strace -Tf -o trace.out
. Observe os números entre colchetes angularestrace.out
para a chamada do sistema que leva muito tempo para ser concluída.Você também pode monitorar o tempo entre as chamadas do sistema para ver qual processamento de um arquivo leva muito tempo para ser concluído. Para fazer isso, prefixe o processo com o qual você executa
strace -rf -o trace.out
. Verifique o número antes de cada chamada do sistema para verificar se há intervalos longos de chamada do sistema. Volte a partir desse ponto procurandoopen
chamadas para ver qual era o arquivo que estava sendo processado.Se isso não ajudar, você pode criar um perfil de seu processo para ver onde ele passa a maior parte do tempo.
fonte