J'étudie les accélérations potentielles de complétion de code tout en utilisant le mécanisme de complétion de code de clang. Le flux décrit ci-dessous est ce que j'ai trouvé dans rtags , par Anders Bakken.
Les unités de traduction sont analysées par un fichier de surveillance de démon pour les modifications. Cela se fait en appelant clang_parseTranslationUnit
et les fonctions associées (reparse*
, dispose*
). Lorsque l'utilisateur demande un achèvement sur une ligne et une colonne données dans un fichier source, le démon transmet l'unité de traduction mise en cache pour la dernière version enregistrée du fichier source et le fichier source actuel à clang_codeCompleteAt
. ( Documents Clang CodeComplete ).
Les drapeaux sont passés à clang_parseTranslationUnit
(de CompletionThread :: process, ligne 271 ) sont CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes
. Les drapeaux sont passés à clang_codeCompleteAt
(de CompletionThread :: process, ligne 305 ) sont CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns
.
L'appel à clang_codeCompleteAt
est très lent - il faut environ 3 à 5 secondes pour obtenir un achèvement même dans les cas où l'emplacement d'achèvement est un code d'accès membre légitime, un sous-ensemble du cas d'utilisation prévu mentionné dans la documentation de clang_codeCompleteAt
. Cela semble beaucoup trop lent par IDE normes de complétion de code. Existe-t-il un moyen d'accélérer cela?
Le problème de clang_parseTranslationUnit est que le préambule précompilé n'est pas réutilisé la deuxième fois, ce qu'on appelle l'achèvement de code. Calculer le préambule de précompilation prend plus de 90% de ce temps, vous devez donc autoriser la réutilisation du préambule précompilé dès que possible.
Par défaut, il est réutilisé la troisième fois qui est appelé pour analyser/analyser l'unité de traduction.
Jetez un œil à cette variable 'PreambleRebuildCounter' dans ASTUnit.cpp.
Un autre problème est que ce préambule est enregistré dans un fichier temporaire. Vous pouvez conserver le préambule précompilé en mémoire au lieu d'un fichier temporaire. Ce serait plus rapide. :)
Parfois, des retards de cette ampleur sont dus à des délais d'attente sur les ressources réseau (partages NFS ou CIFS sur un chemin de recherche de fichiers ou des sockets). Essayez de surveiller le temps nécessaire à chaque appel système en préfixant le processus de votre exécution avec strace -Tf -o trace.out
. Regardez les chiffres entre parenthèses dans trace.out
pour l'appel système qui prend beaucoup de temps.
Vous pouvez également surveiller le temps entre les appels système pour voir quel traitement d'un fichier prend trop de temps. Pour ce faire, préfixez le processus de votre exécution avec strace -rf -o trace.out
. Regardez le numéro avant chaque appel système pour rechercher de longs intervalles d'appel système. Revenez en arrière à partir de ce point à la recherche d'appels open
pour voir quel fichier était en cours de traitement.
Si cela n'aide pas, vous pouvez profile votre processus pour voir où il passe la plupart de son temps.