Si scopre che le prestazioni selvaggiamente variabili erano legate alla garbage collection. Ogni chiamata alla funzione diventerebbe più lenta fino a quando non verrà eseguita una garbage collection. Con stock emacs, gc veniva eseguito ogni paio di secondi, ma avevo una riga nel mio init.el per migliorare il tempo di avvio che impostava gc-contro-soglia a 20 MB e ciò significava che gc veniva eseguito molto più raramente, facendo sì che i benchmark riferire tempi più lenti e più lenti fino a quando un paio di minuti è stato eseguito un gc, quindi i tempi sarebbero precipitati ed essere di nuovo veloci.
Dopo aver ripristinato il valore predefinito di gc-cons-threshhold, il benchmarking è diventato più semplice.
Ho quindi profilato per la memoria con il profiler incorporato ( M-x profiler-start
) e ho scoperto che le chiamate a sintassi-pps causavano la maggior parte delle allocazioni, quindi dopo qualche ottimizzazione per chiamare sintassi-pps meno spesso ho raggiunto prestazioni accettabili.
L'uso della modalità jit-lock (aggiunta di una funzione tramite jit-lock-register) sembra essere il modo più semplice per far funzionare in modo affidabile il blocco dei font su più righe, quindi quello è stato il metodo che ho scelto.
Modifica: dopo aver scoperto che le prestazioni non erano ancora abbastanza buone in buffer molto grandi, ho trascorso molto tempo a ottimizzare l'uso e l'allocazione della CPU, misurando i miglioramenti delle prestazioni con il profiler Emacs incorporato ( M-x profiler-start
). Tuttavia, Emacs continua a balbettare e si blocca quando si scorre rapidamente attraverso buffer molto grandi. La rimozione della funzione jit-lock con cui mi sono registrato jit-lock-register
rimuoveva la balbuzie e si blocca, ma la creazione di profili ha mostrato che la funzione jit-lock si completerebbe in circa 8 ms, che dovrebbe essere abbastanza veloce per uno scorrimento regolare. La rimozione della chiamata jit-lock-register
e invece l'utilizzo di un normale matcher di blocco dei caratteri e delle parole chiave ha risolto il problema.
TLDR: farlo è stato lento e balbettare:
(defun my-font-lock-function (start end)
"Set faces for font-lock between START and END.")
(jit-lock-register 'my-font-lock-function)
In questo modo è stato veloce e non balbettare:
(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))))