Schnellere Code-Vervollständigung mit Klirren

108

Ich untersuche mögliche Beschleunigungen der Code-Vervollständigung, während ich den Code-Vervollständigungsmechanismus von clang verwende. Der unten beschriebene Ablauf ist der, den ich in rtags von Anders Bakken gefunden habe.

Übersetzungseinheiten werden von einem Dämon analysiert, der Dateien auf Änderungen überwacht. Dies geschieht durch aufgerufene clang_parseTranslationUnitund verwandte Funktionen ( reparse*, dispose*). Wenn der Benutzer eine Vervollständigung in einer bestimmten Zeile und Spalte in einer Quelldatei anfordert, übergibt der Dämon die zwischengespeicherte Übersetzungseinheit für die zuletzt gespeicherte Version der Quelldatei und die aktuelle Quelldatei an clang_codeCompleteAt. ( Clang CodeComplete-Dokumente ).

Die an clang_parseTranslationUnit(von CompletionThread :: process, Zeile 271 ) übergebenen Flags sind CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes. Die an clang_codeCompleteAt(von CompletionThread :: process, Zeile 305 ) übergebenen Flags sind CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns.

Der Aufruf von clang_codeCompleteAtist sehr langsam - es dauert ungefähr 3-5 Sekunden, um eine Vervollständigung zu erhalten, selbst wenn der Vervollständigungsort ein legitimer Mitgliedszugriffscode ist, eine Teilmenge des beabsichtigten Anwendungsfalls, der in der Dokumentation von erwähnt wird clang_codeCompleteAt. Dies scheint nach IDE-Code-Vervollständigungsstandards viel zu langsam zu sein. Gibt es eine Möglichkeit, dies zu beschleunigen?

Pradhan
quelle
8
Ich würde Ihnen gerne helfen, aber wir brauchen weitere Einzelheiten. Beispielcode wäre für den Anfang gut
raph.amiard
1
Klingeln. Gibt es Fortschritte bei diesem Problem?
Mehrwolf
4
@Cameron Entschuldigung für die lange Verzögerung bei der Rückmeldung. Ich habe versucht , alle 8 Kombinationen CXTranslationUnit_SkipFunctionBodies, CXCodeComplete_IncludeMacros, CXCodeComplete_IncludeCodePatternsund nicht sehen einen signifikanten Unterschied auf der Code - Basis mit denen ich arbeite. Alle durchschnittlich etwa 4 Sekunden pro Abschluss. Ich denke, das liegt nur an der Größe der TUs. CXTranslationUnit_PrecompiledPreamblesorgt dafür, dass reparseTUes sehr schnell geht. Aber auch mit CXTranslationUnit_CacheCompletionResults, clang_codeCompleteAtlangsam ist schmerzlich für meinen Anwendungsfall.
Pradhan
1
@Mehrwolf Ack. Siehe obigen Kommentar.
Pradhan
7
Hmm, das ist unglücklich. Können Sie die Langsamkeit der Fertigstellung auf einer öffentlich zugänglichen Übersetzungseinheit (z. B. Open Source) reproduzieren? Es wäre hilfreich, wenn wir dies selbst reproduzieren könnten. Die Fertigstellung sollte ungefähr so ​​schnell sein wie die Analyse, da dies intern erfolgt (es wird ein spezielles Token für die Code-Vervollständigung eingefügt und bis zu diesem Punkt analysiert).
Cameron

Antworten:

6

Das Problem von clang_parseTranslationUnit besteht darin, dass die vorkompilierte Präambel beim zweiten Mal, das als Code-Vervollständigung bezeichnet wird, nicht wiederverwendet wird. Die Berechnung der vorkompilierten Präambel dauert mehr als 90% dieser Zeit. Sie sollten daher zulassen, dass die vorkompilierte Präambel so bald wie möglich wiederverwendet wurde.

Standardmäßig wird es beim dritten Aufruf der Analyse- / Analyse-Übersetzungseinheit wiederverwendet.

Schauen Sie sich diese Variable 'PreambleRebuildCounter' in ASTUnit.cpp an.

Ein weiteres Problem ist, dass diese Präambel in einer temporären Datei gespeichert wird. Sie können die vorkompilierte Präambel anstelle einer temporären Datei im Speicher behalten. Es wäre schneller. :) :)

GutiMac
quelle
Genial! Das klingt so, als würde es zum eigentlichen Problem kommen. Werfen Sie einen Blick darauf und lassen Sie es Sie wissen. Vielen Dank!
Pradhan
OK! Lass es mich wissen, wenn es bei dir funktioniert! und wenn Sie irgendwelche Fragen haben, können Sie mich gerne fragen !!!!
GutiMac
4

Manchmal sind Verzögerungen dieser Größenordnung auf Zeitüberschreitungen bei Netzwerkressourcen zurückzuführen (NFS- oder CIFS-Freigaben in einem Dateisuchpfad oder Sockets). Versuchen Sie, die Zeit zu überwachen, die jeder Systemaufruf benötigt, indem Sie dem Prozess, mit dem Sie ausgeführt werden, ein Präfix voranstellen strace -Tf -o trace.out. Sehen Sie sich die Zahlen in spitzen Klammern trace.outfür den Systemaufruf an, dessen Abschluss lange dauert.

Sie können auch die Zeit zwischen Systemaufrufen überwachen , um festzustellen, welche Verarbeitung einer Datei zu lange dauert. Stellen Sie dazu den Prozess voran, mit dem Sie ausgeführt werden strace -rf -o trace.out. Überprüfen Sie die Nummer vor jedem Systemaufruf, um nach langen Systemaufrufintervallen zu suchen. Gehen Sie von diesem Punkt aus rückwärts und suchen Sie nachopen Aufrufen, um zu sehen, welche Datei verarbeitet wurde.

Wenn dies nicht hilft, können Sie Ihren Prozess profilieren, um zu sehen, wo er die meiste Zeit verbringt.

Diomidis Spinellis
quelle