Completamento del codice più veloce con clang


108

Sto indagando su potenziali accelerazioni di completamento del codice durante l'utilizzo del meccanismo di completamento del codice di clang. Il flusso descritto di seguito è quello che ho trovato in rtags , di Anders Bakken.

Le unità di traduzione vengono analizzate da un demone che controlla i file per le modifiche. Questo viene fatto dalle clang_parseTranslationUnitfunzioni chiamate e correlate ( reparse*, dispose*). Quando l'utente richiede un completamento in una determinata riga e colonna in un file sorgente, il demone passa l'unità di traduzione memorizzata nella cache per l'ultima versione salvata del file sorgente e il file sorgente corrente a clang_codeCompleteAt. ( Documenti Clang CodeComplete ).

I flag passati a clang_parseTranslationUnit(da CompletionThread :: process, riga 271 ) sono CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes. I flag passati a clang_codeCompleteAt(da CompletionThread :: process, riga 305 ) sono CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns.

La chiamata a clang_codeCompleteAtè molto lenta: occorrono circa 3-5 secondi per ottenere un completamento anche nei casi in cui la posizione di completamento è un codice di accesso membro legittimo, un sottoinsieme del caso d'uso previsto menzionato nella documentazione di clang_codeCompleteAt. Questo sembra troppo lento per gli standard di completamento del codice IDE. C'è un modo per accelerare questo processo?


8
Sarei felice di aiutarti, ma abbiamo bisogno di maggiori dettagli. Il codice di esempio sarebbe utile per iniziare
raph.amiard

1
Ping. Ci sono progressi su questo problema?
Mehrwolf

4
@Cameron Mi dispiace per il lungo ritardo nel risponderti. Ho provato tutte le combinazioni di 8 CXTranslationUnit_SkipFunctionBodies, CXCodeComplete_IncludeMacros, CXCodeComplete_IncludeCodePatternse non ho visto una differenza significativa sulla base di codice con cui sto lavorando. Tutti hanno una media di circa 4 secondi per completamento. Immagino che questo sia solo a causa delle dimensioni delle TU. CXTranslationUnit_PrecompiledPreambleassicura reparseTUè molto veloce. Tuttavia, anche con CXTranslationUnit_CacheCompletionResults, clang_codeCompleteAtè dolorosamente lento per il mio caso d'uso.
Pradhan

1
@Mehrwolf Ack. Vedi commento sopra.
Pradhan

7
Hmm, è un peccato. Riesci a riprodurre la lentezza di completamento su un'unità di traduzione disponibile al pubblico (es. Open source)? Sarebbe utile se fossimo in grado di riprodurlo da soli. Il completamento dovrebbe essere più o meno veloce come il reparse, poiché è quello che fa internamente (inietta uno speciale token di completamento del codice e analizza fino a quel punto).
Cameron

Risposte:


6

Il problema di clang_parseTranslationUnit è che il preambolo precompilato non viene riutilizzato la seconda volta che viene chiamata completamento del codice. Calcolare il preambolo precompilato richiede più del 90% di questi tempi, quindi dovresti consentire che il preambolo precompilato sia riutilizzato non appena possibile.

Per impostazione predefinita, viene riutilizzato la terza volta che viene chiamato per analizzare / analizzare l'unità di traduzione.

Dai un'occhiata a questa variabile "PreambleRebuildCounter" in ASTUnit.cpp.

Un altro problema è che questo preambolo viene salvato in un file temporaneo. È possibile mantenere il preambolo precompilato in memoria invece di un file temporaneo. Sarebbe più veloce. :)


Eccezionale! Sembra che arrivi al vero problema. Daremo un'occhiata a questo e ti farò sapere. Grazie!
Pradhan

ok! fammi sapere se funziona per te! e se avete domande non esitate a chiedermelo !!!!
GutiMac

4

A volte ritardi di questa entità sono dovuti a timeout sulle risorse di rete (condivisioni NFS o CIFS su un percorso di ricerca file o socket). Prova a monitorare il tempo impiegato da ciascuna chiamata di sistema per completare anteponendo il processo con cui esegui strace -Tf -o trace.out. Guarda i numeri tra parentesi angolari trace.outper la chiamata di sistema che richiede molto tempo per essere completata.

È inoltre possibile monitorare il tempo tra le chiamate di sistema per vedere quale elaborazione di un file impiega troppo tempo per essere completata. Per fare ciò, anteponi il processo con cui corri strace -rf -o trace.out. Guarda il numero prima di ogni chiamata di sistema per cercare lunghi intervalli di chiamata di sistema. Torna indietro da quel punto alla ricerca di openchiamate per vedere quale era il file che era in fase di elaborazione.

Se questo non aiuta, puoi profilare il tuo processo per vedere dove trascorre la maggior parte del suo tempo.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.