font-lock – Optimización del rendimiento del bloqueo de fuentes

Pregunta:

Quiero realizar una variante de coincidencia de bloqueo de fuente anclada. Tengo definiciones de funciones que comienzan con una lista de nombres y quiero que esos nombres se resalten dentro del cuerpo de la función.

Creé una función que hace esto y la registré como una función jit-lock con jit-lock-register, sin embargo, el rendimiento es bastante pobre y el desplazamiento se retrasa en archivos más grandes.

  • ¿Cómo puedo medir el desempeño? Si solo llamo por tiempo a mi función en un archivo grande (con tiempo de flotación antes y después o con elp) obtengo un rendimiento muy variable, se tarda entre 0,65 y 12 segundos. ¿Existe una forma recomendada de comparar el rendimiento del bloqueo de fuentes?
  • ¿Hay alguna diferencia en el rendimiento entre un comparador anclado definido en font-lock-keywords y agregar una función a través de jit-lock-register?

Editar: Parece que la variabilidad en el rendimiento está relacionada con la recolección de basura, las invocaciones de mi función jit-lock se vuelven sucesivamente más lentas con cada invocación hasta que se ejecuta la recolección de basura, momento en el que vuelven a ser rápidas.

Respuesta:

Resulta que el rendimiento enormemente variable estaba relacionado con la recolección de basura. Cada llamada a la función sería más lenta hasta que se ejecutara una recolección de basura. Con stock emacs, gc se ejecutaba cada dos segundos, pero tenía una línea en mi init.el para mejorar el tiempo de inicio que establecía gc-cons -reshold en 20 MB, y eso significaba que gc se ejecutaba con mucha menos frecuencia, lo que provocaba que los puntos de referencia se informan tiempos cada vez más lentos hasta que se ejecuta un gc después de un par de minutos, luego los tiempos se desploman y vuelven a ser rápidos.

Después de volver al valor predeterminado gc-cons-threshhold, la evaluación comparativa se volvió más fácil.

Luego hice un perfil de memoria con el generador de perfiles integrado ( Mx profiler-start ) y descubrí que las llamadas a syntax-ppss causaban la mayoría de las asignaciones, por lo que después de algunas optimizaciones para llamar a syntax-ppss con menos frecuencia, logré un rendimiento aceptable.

Usar jit-lock-mode (agregar una función a través de jit-lock-register) parece ser la forma más fácil de lograr que el bloqueo de fuentes de múltiples líneas funcione de manera confiable, por lo que ese fue el método que elegí.

Editar: Después de descubrir que el rendimiento aún no era lo suficientemente bueno en búferes muy grandes, pasé mucho tiempo optimizando el uso y la asignación de la CPU, midiendo las mejoras de rendimiento con el generador de perfiles de Emacs integrado ( Mx profiler-start ). Sin embargo, Emacs todavía tartamudearía y colgaría cuando se desplazara rápidamente a través de búferes muy grandes. Eliminar la función jit-lock que jit-lock-register con jit-lock-register eliminaría el tartamudeo y los bloqueos, pero la creación de perfiles mostró que la función jit-lock se completaba en unos 8 ms, lo que debería ser lo suficientemente rápido para un desplazamiento suave. La eliminación de la llamada a jit-lock-register y, en su lugar, el uso de un comparador de palabras clave font-lock-normal resolvió el problema.

TLDR: Hacer esto fue lento y tartamudearía:

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

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

Hacer esto fue rápido y no tartamudearía:

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

Leave a Comment

Your email address will not be published.

Scroll to Top

istanbul avukat

-

web tasarım