Виявляється, що дивовижна ефективність була пов'язана зі збиранням сміття. Кожен дзвінок у функцію проходитиме повільніше, поки не буде запущено збирання сміття. З біржовими emacs, gc запускався кожні пару секунд, але у мене був рядок у моєму init.el, щоб поліпшити час запуску, який встановив gc-мінус-поріг у 20 Мб, і це означало, що gc запускається набагато рідше, викликаючи показники для повідомляйте про повільніші та повільніші терміни, доки GC не запуститься через пару хвилин, тоді часи спадатимуть і знову стануть швидкими.
Після повернення до gc-cons-threshold за замовчуванням тестування стало простішим.
Потім я профілював пам'ять за допомогою вбудованого profiler ( M-x profiler-start
) і виявив, що виклики до синтаксису-ppss викликали найбільше виділень, тому після деякої оптимізації для виклику синтаксису-ppss рідше я досягав прийнятних показників.
Використання режиму jit-lock (додавання функції через jit-lock-register), здається, найпростіший спосіб змусити надійно працювати багаторядкове блокування шрифту, тому це був обраний нами метод.
Редагувати: Після того, як виявив, що продуктивність все ще недостатньо хороша в дуже великих буферах, я витратив багато часу на оптимізацію використання та розподілення процесора, вимірюючи поліпшення продуктивності за допомогою вбудованого в Emacs profiler ( M-x profiler-start
). Однак Emacs все одно заїкається і зависає, коли швидко прокручує дуже великі буфери. Якщо вилучити функцію jit-lock, яку я зареєстрував, jit-lock-register
було б видалити заїкання та зависання, але профілювання показало, що функція jit-lock завершиться приблизно за 8 мс, що має бути досить швидким для плавного прокручування. Видалення виклику jit-lock-register
та замість цього використання звичайного відповідника шрифтових ключових слів вирішило проблему.
TLDR: Робити це було повільно і заїкалось:
(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")
(jit-lock-register 'my-font-lock-function)
Робити це було швидко і не заїкатися:
(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))))