La sugerencia de establecer debug-on-quit
en t
para que pueda averiguar qué es lo que Emacs está haciendo es una buena idea. Puede pensar en esto como una forma de muestreo de perfiles con una sola muestra: a menudo, una sola muestra es todo lo que necesita.
Actualización: partir de la versión 24.3, Emacs contiene dos perfiladores. Hay un (nuevo) generador de perfiles de muestreo en profiler.el
, y un perfilador de instrumentos (antiguo) en elp.el
.
El generador de perfiles de muestreo es documented here. Es bastante fácil de usar:
Para comenzar a perfilar, escriba M-x profiler-start
. Puede elegir el perfil según el uso del procesador, el uso de la memoria o ambos. Después de hacer un poco de trabajo, escriba M-x profiler-report
para mostrar un búfer de resumen para cada recurso que eligió para crear un perfil. Cuando haya terminado de perfilar, escriba M-x profiler-stop
.
Aquí hay un ejemplo de salida de una sesión de generador de perfiles cpu+mem
con el Perforce/Emacs integration que mantengo. Expandí la función más alta (progn
) para averiguar where the CPU time and memory use is coming from.
Function Bytes %
- progn 26,715,850 29%
- let 26,715,850 29%
- while 26,715,850 29%
- let 26,715,850 29%
- cond 26,715,850 29%
- insert 26,715,850 29%
+ c-after-change 26,713,770 29%
+ p4-file-revision-annotate-links 2,080 0%
+ let 20,431,797 22%
+ call-interactively 12,767,261 14%
+ save-current-buffer 10,005,836 11%
+ while 8,337,166 9%
+ p4-annotate-internal 5,964,974 6%
+ p4-annotate 2,821,034 3%
+ let* 2,089,810 2%
Se puede ver que el culpable es c-after-change
, por lo que parece como si pudiera ahorrar mucho tiempo de CPU y de memoria por locally binding inhibit-modification-hooks
to t
around this code.
También puede usar el Emacs Lisp Profiler. Esto no está suficientemente documentado: deberá leer los comentarios en elp.el
para obtener más información, pero básicamente ejecuta elp-instrument-package
para activar la creación de perfiles para todas las funciones con un prefijo dado y luego elp-results
para ver los resultados.
He aquí alguna salida típica después de escribir M-x elp-instrument-package RET c- RET
, fontifying 4.000 líneas de C, y luego ejecutar elp-results
(y usando elp-sort-by-function
para ordenar por recuento de llamadas):
Function Name Call Count Elapsed Time Average Time
============================= ========== ============ ============
c-skip-comments-and-strings 107 0.0 0.0
c-valid-offset 78 0.0 0.0
c-set-offset 68 0.031 0.0004558823
c-end-of-macro 52 0.0 0.0
c-neutralize-CPP-line 52 0.0 0.0
c-font-lock-invalid-string 20 0.0 0.0
c-set-style-1 19 0.031 0.0016315789
...
En su caso particular, el generador de perfiles no ayuda inmediatamente, porque no sabes qué paquete tiene la culpa. Pero si puede adivinar (o use debug-on-quit
para encontrarlo con seguridad), el generador de perfiles puede ayudarlo a diagnosticar el problema en detalle.
Buen punto, hago eval-expression todo el tiempo, pero este modo de depuración hadn' t se me ocurrió inicialmente. – EnigmaCurry
No desea evaluar cada sexp a su vez (a menos que tenga muy pocos). Use una búsqueda binaria, con 'eval-region '. – Drew