Optymalizacja wydajności blokowania czcionek

13

Chcę wykonać wariant dopasowania zakotwiczonego blokowania czcionek. Mam definicje funkcji, które zaczynają się od listy nazw, i chcę, aby te nazwy były podświetlone w treści funkcji.

Stworzyłem funkcję, która to robi, i zarejestrowałem ją jako funkcję blokady jit z rejestrem blokady jit, jednak wydajność jest dość niska i przewijanie opóźnień w większych plikach.

  • Jak mogę zmierzyć wydajność? Jeśli po prostu czas na wywołanie mojej funkcji na dużym pliku (z czasem zmiennoprzecinkowym przed i po lub z elpem) mam bardzo różną wydajność, zajmuje to od 0,65 do 12 sekund. Czy istnieje zalecany sposób na sprawdzenie wydajności blokowania czcionek?
  • Czy jest jakaś różnica w wydajności między zakotwiczonym dopasowaniem zdefiniowanym w słowach kluczowych blokujących czcionkę a dodaniem funkcji za pomocą rejestru blokującego?

Edycja: Wygląda na to, że zmienność wydajności jest związana z odśmiecaniem, wywołania mojej funkcji blokowania jit stają się coraz wolniejsze przy każdym wywołaniu, aż do uruchomienia odśmiecania, w którym to momencie znów stają się szybkie.

Joakim Hårsman
źródło
W przypadku pierwszego elementu wypróbuj profiler.
Malabarba
Mogę (i użyłem) również profilera, aby zobaczyć, które części mojego kodu wymagają czasu, ale ponieważ wydajność jest tak niespójna, trudno jest stwierdzić, czy wprowadzone zmiany są poprawą, czy nie.
Joakim Hårsman
Czy masz jakiś kod, który możemy przetestować? To może nam bardzo pomóc.
PythonNut,
1
Chociaż nie chodzi o profilowanie ani mikrooptymalizacje, per se: Odkryłem, że pakiet font-lock-studio jest kolejnym pomocnym narzędziem do zrozumienia wydajności blokowania czcionek. Może pomóc w taki sam sposób, jak każdy inny interaktywny debugger krokowy - możesz odkryć, że ścieżki wykonania nie są tym, czego oczekujesz, i to jest główny problem z wydajnością.
Greg Hendershott
Dzięki za poradę na temat font-lock-studio, to jest niesamowite! Nie pomaga to jednak w blokowaniu blokad, ale na pewno działa we wszystkim innym.
Joakim Hårsman

Odpowiedzi:

8

Okazuje się, że bardzo zróżnicowana wydajność była związana z odśmiecaniem. Każde wywołanie funkcji będzie działało wolniej, dopóki nie zostanie uruchomione czyszczenie pamięci. Z zapasowymi emacsami, gc był uruchamiany co kilka sekund, ale miałem init w linii, aby skrócić czas uruchamiania, który ustawił próg gc-cons na 20 MB, a to oznaczało, że gc był uruchamiany znacznie rzadziej, powodując zgłaszaj coraz wolniejsze taktowanie, aż gc zostanie uruchomiony po kilku minutach, wtedy czasy zaczną spadać i znów będą szybkie.

Po przywróceniu domyślnej wartości gc-cons-threshhold testowanie stało się łatwiejsze.

Następnie profilowałem pod kątem pamięci za pomocą wbudowanego profilera ( M-x profiler-start) i odkryłem, że wywołania do składni-ppss powodowały najwięcej alokacji, więc po pewnej optymalizacji w celu wywołania składni-pps rzadziej osiągałem akceptowalną wydajność.

Korzystanie z trybu blokowania czcionek (dodawanie funkcji przez rejestr blokady blokad) wydaje się być najłatwiejszym sposobem na niezawodne blokowanie czcionek wielowierszowych, dlatego wybrałem tę metodę.

Edycja: Po odkryciu, że wydajność wciąż nie była wystarczająca w bardzo dużych buforach, spędziłem dużo czasu optymalizując użycie procesora i alokację procesora, mierząc poprawę wydajności za pomocą wbudowanego narzędzia Emacs profiler ( M-x profiler-start). Jednak Emacs nadal się jąka i zawiesza podczas szybkiego przewijania bardzo dużych buforów. Usunięcie funkcji blokady jit, w której się zarejestrowałem, jit-lock-registerspowoduje usunięcie jąkania i zawieszenie się, ale profilowanie pokazało, że funkcja blokady jit zakończyła się po około 8 ms, co powinno być wystarczająco szybkie, aby płynnie przewijać. Usunięcie połączenia z, jit-lock-registera zamiast tego za pomocą zwykłego dopasowywania czcionek blokujących słowa kluczowe rozwiązało problem.

TLDR: Robienie tego było powolne i zacinało się:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(jit-lock-register 'my-font-lock-function)

Zrobienie tego było szybkie i nie zacinało się:

(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")

(defun my-font-lock-matcher (limit)
    (my-font-lock-function (point) limit)
   nil)

(setq font-lock-defaults
  (list 
     ...
    ;; Note that the face specified here doesn't matter since
    ;; my-font-lock-matcher always returns nil and sets the face on
    ;; its own.
    `(my-font-lock-matcher (1 font-lock-keyword-face nil))))
Joakim Hårsman
źródło
Czy możesz udostępnić użyty kod? Twoje rozwiązanie może pomóc innym, którzy chcą osiągnąć to samo.
Manuel Uberti
Tak naprawdę nie użyłem żadnego konkretnego kodu, po prostu nazwałem składnię-pps mniej. Możesz sprawdzić kod, o którym mowa, tutaj: bitbucket.org/harsman/dyalog-mode/src/… Poszukaj dyalog-fontify-locals.
Joakim Hårsman
Myślę, że dyalog-fontify-locals-matcherpowinno być my-font-lock-matcheri jednym z takich endpowinno być limit. W każdym razie naprawdę interesujące odkrycie!
Lindydancer
@Lindydancer: Tak, dziękuję. Naprawiony.
Joakim Hårsman
1
Re: gc-cons-thresholdjeśli masz problemy z wewnętrznymi wartościami wyłącznie w celu skrócenia czasu uruchamiania, sugeruję, abyś emacs-startup-hookpóźniej je przywrócił.
phils