Badam potencjalne przyspieszenia uzupełniania kodu podczas korzystania z mechanizmu uzupełniania kodu Clang. Przepływ opisany poniżej jest tym, co znalazłem w rtagach autorstwa Andersa Bakkena .
Jednostki tłumaczeniowe są analizowane przez demona monitorujące pliki pod kątem zmian. Robią to wywołane clang_parseTranslationUnit
i powiązane funkcje ( reparse*
, dispose*
). Gdy użytkownik zażąda uzupełnienia w danej linii i kolumnie w pliku źródłowym, demon przekazuje buforowaną jednostkę tłumaczeniową dla ostatnio zapisanej wersji pliku źródłowego i bieżącego pliku źródłowego do clang_codeCompleteAt
. ( Dokumenty Clang CodeComplete ).
Flagi przekazywane do clang_parseTranslationUnit
(z CompletionThread :: process, wiersz 271 ) to CXTranslationUnit_PrecompiledPreamble|CXTranslationUnit_CacheCompletionResults|CXTranslationUnit_SkipFunctionBodes
. Flagi przekazane do clang_codeCompleteAt
(z CompletionThread :: process, wiersz 305 ) to CXCodeComplete_IncludeMacros|CXCodeComplete_IncludeCodePatterns
.
Wywołanie clang_codeCompleteAt
jest bardzo powolne - uzyskanie zakończenia zajmuje około 3-5 sekund, nawet w przypadkach, gdy lokalizacją zakończenia jest prawidłowy kod dostępu członka, podzbiór zamierzonego przypadku użycia wymieniony w dokumentacji clang_codeCompleteAt
. Wydaje się to zbyt wolne w świetle standardów uzupełniania kodu IDE. Czy jest sposób, aby to przyspieszyć?
CXTranslationUnit_SkipFunctionBodies
,CXCodeComplete_IncludeMacros
,CXCodeComplete_IncludeCodePatterns
i nie zobaczyć znaczną różnicę w kodzie pracuję z. Wszystkie z nich mają średnio około 4 sekund na ukończenie. Wydaje mi się, że dzieje się tak tylko z powodu rozmiaru jednostek tłumaczeniowych.CXTranslationUnit_PrecompiledPreamble
zapewnia, żereparseTU
jest bardzo szybki. Jednak nawet zCXTranslationUnit_CacheCompletionResults
,clang_codeCompleteAt
jest boleśnie powolny w moim przypadku użycia.Odpowiedzi:
Problem, który ma clang_parseTranslationUnit polega na tym, że prekompilowana preambuła nie jest ponownie używana za drugim razem, co jest nazywane uzupełnianiem kodu. Oblicz, że prekompilowana preambuła zajmuje więcej niż 90% tego czasu, więc powinieneś pozwolić, aby prekompilowana preambuła została ponownie wykorzystana tak szybko, jak to możliwe.
Domyślnie jest ponownie używany po raz trzeci, gdy jest wywoływany w celu przeanalizowania / ponownej analizy jednostki tłumaczeniowej.
Przyjrzyj się tej zmiennej „PreambleRebuildCounter” w ASTUnit.cpp.
Innym problemem jest to, że ta preambuła jest zapisywana w pliku tymczasowym. Możesz zachować prekompilowaną preambułę w pamięci zamiast w pliku tymczasowym. Byłoby szybciej. :)
źródło
Czasami opóźnienia tej wielkości są spowodowane przekroczeniem limitu czasu zasobów sieciowych (udziałów NFS lub CIFS na ścieżce wyszukiwania plików lub gniazdach). Spróbuj monitorować czas potrzebny do zakończenia każdego wywołania systemowego, poprzedzając proces, z którym uruchomiłeś
strace -Tf -o trace.out
. Spójrz na liczby w nawiasach ostrych,trace.out
aby sprawdzić wywołanie systemowe, które zajmuje dużo czasu.Możesz także monitorować czas między wywołaniami systemowymi, aby sprawdzić, które przetwarzanie pliku trwa zbyt długo. Aby to zrobić, poprzedź proces, z którym uruchamiasz
strace -rf -o trace.out
. Spójrz na numer przed każdym wywołaniem systemowym, aby znaleźć długie interwały wywołań systemowych. Cofnij się od tego punktu, szukającopen
wywołań, aby zobaczyć, który plik był przetwarzany.Jeśli to nie pomoże, możesz sprofilować swój proces, aby zobaczyć, gdzie spędza większość czasu.
źródło