Советы по профилированию неправильного поведения Emacs Lisp? - PullRequest
43 голосов
/ 20 февраля 2009

Я много настраиваю Emacs. Недавно я добавил кое-что в мою конфигурацию .emacs, которая время от времени привязывает мой процессор к 100%, но я действительно не знаю, что это такое.

Если я нажму C-g несколько раз, в конечном итоге я получу сообщение ниже минибуфера, спрашивающего, хочу ли я автоматически сохранять свои файлы, а затем, если я хочу полностью прервать emacs. Если я продолжу говорить нет и продолжаю нажимать C-g, в конце концов я смогу вернуться к запуску emacs как обычно. Примерно через час это случится снова.

Я мог бы продолжать в том же духе, комментируя различные вещи, которые я недавно добавил, перезапуская emacs, пытаясь сузить преступника, но это медленно.

Есть ли способ, которым я могу профилировать Emacs напрямую, чтобы выяснить, какая функция lisp перегружает процессор?

Ответы [ 4 ]

50 голосов
/ 20 февраля 2009

Рекомендуется установить debug-on-quit в t, чтобы вы могли узнать, что задумал Emacs. Вы можете думать об этом как о форме профилирования выборки с одной выборкой: часто вам нужна только одна выборка.


Обновление: Начиная с версии 24.3, Emacs содержит два профилировщика. Существует (новый) профилировщик выборки в profiler.el и (старый) профилировщик инструментов в elp.el.

Профилировщик выборки задокументирован здесь . Это довольно просто использовать:

Чтобы начать профилирование, введите M-x profiler-start. Вы можете выбрать профиль по использованию процессора, использованию памяти или обоим. После некоторой работы введите M-x profiler-report, чтобы отобразить сводный буфер для каждого ресурса, который вы выбрали для профилирования. Когда вы закончите профилирование, введите M-x profiler-stop.

Вот некоторые примеры вывода из сеанса профилировщика cpu+mem с интеграцией Perforce / Emacs , которую я поддерживаю. Я расширил самую верхнюю функцию (progn), чтобы выяснить , где время процессора и использование памяти исходит от .

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%

Вы можете видеть, что виновником является c-after-change, поэтому похоже, что я мог бы сэкономить много процессорного времени и памяти путем локального связывания inhibit-modification-hooks с t вокруг этого кода .


Вы также можете использовать Emacs Lisp Profiler. Это недостаточно документировано: вам нужно прочитать комментарии в elp.el для деталей, но в основном вы запускаете elp-instrument-package, чтобы включить профилирование для всех функций с заданным префиксом, а затем elp-results, чтобы увидеть результаты.

Вот несколько типичных выходных данных после ввода M-x elp-instrument-package RET c- RET, озвучивания 4000 строк C, а затем запуска elp-results (и использования elp-sort-by-function для сортировки по количеству вызовов):

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

В вашем конкретном случае профилировщик не помогает сразу, потому что вы не знаете, какой пакет виноват. Но если вы можете сделать предположение (или использовать debug-on-quit, чтобы точно его найти), то профилировщик может помочь вам детально диагностировать проблему.

8 голосов
/ 20 февраля 2009

Вы пробовали: Options->Enter debugger on Quit/C-g? (это на emacs22)

Если вам нужно отладить запуск emacs: используйте emacs -q --no-site-file, посетите ваш .emacs (или site-start.el или любой другой), активируйте пункт меню Options->Enter debugger on Quit/C-g, а затем пункт меню Emacs-Lisp->Evaluate buffer и C-g когда кажется, что он замерзает. Там может быть более простой способ сделать это .........

6 голосов
/ 19 марта 2009

С помощью dope.el вы можете профилировать целые .emacs или несколько файлов elisp, загруженных при запуске. Загрузите его с www.gnufans.net / ~ deego / pub / emacspub / lisp-mine / dope /

M-x dope-quick-start покажет небольшое введение.

Редактировать: Первоначальный URL больше не существует, но на Git Hub есть рабочее зеркало:
https://raw.github.com/emacsmirror/dope/master/dope.el

5 голосов
/ 20 февраля 2009

Строго говоря, это не ответ на ваш вопрос, но вместо того, чтобы делать закомментирование и перезапуск, вы можете запустить emacs с опцией -q, загрузить ваши .emacs в буфер и оценить каждый секср сам с помощью Cx Ce выслеживает обидчика.

...