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.


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))))

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.