TL; DR У меня такое огромное количество пакетов, что это мешает моему запуску. Если вы не верите в это, читайте дальше.
Время запуска моего Emacs довольно мало. Я не пользуюсьuse-package
, я просто установил тонны хуков и autoload
s, чтобы почти весь код был отложен. На самом деле все загружается менее чем за полсекунды, несмотря на то, что это выглядит как сумасшедший беспорядок.
Тем не менее, со временем я заметил, что мое время запуска становится немного медленнее, необъяснимым образом. Это в конечном итоге дошло до того, что время запуска ≥ 1 секунды. Мне наконец то надоело и я в корне закопался в проблеме. В конце концов я закомментировал весь ~/.emacs
файл и обнаружил, что время запуска все еще составляло ≥ 1 секунды. На самом деле, он только сбрил ~ 0.2
секунды, иногда даже меньше. Затем я попытался emacs -q
и обнаружил, что время запуска было ~0.1
секунд.
Изучив этот раздел руководства Elisp, я выяснил, почему emacs -q
так сильно сокращается время запуска. По-видимомуemacs -q
мешает Emacs делать три вещи при запуске:
- загрузка вашего файла инициализации
- загружая ваш
default.el
файла - призвание
package-initialize
Мы уже исключили мой файл инициализации, поскольку комментирование всего моего файла ~/.emacs
почти ничего не делает. Я не использую default.el
файл, так что это также исключено. Который оставляет package-initialize
в качестве виновника удара производительности.
Зачем package-initialize
занимать так много времени запуска? Это был первый вопрос, который я задал себе. Разве я не загружаю все? Ну да. Но это именно проблема.
Я нашел этот пост который объясняет, что «активация» пакетов состоит из чтения файлов автозагрузки и установки путей загрузки. Это, очевидно, влечет за собой штраф ввода-вывода, когда у вас много пакетов, потому что у вас есть много файлов автозагрузки для чтения и множество путей для установки. К сожалению, без этого задача управления автозагрузками попадает в руки пользователя. Другими словами, не позволяя package.el
сканировать файловую систему для автозагрузки файлов и путей, мне пришлось бы самому управлять этим, что может быть утомительным и подверженным ошибкам процессом.
Я бы предпочел не идти по этому пути. В настоящее время у меня 116 пакетов, из которых 107 из ELPA и 25 из которых являются зависимостями. Я уверен, что это колоссальное число - то, что так сильно ухудшает мою производительность. Но я в затруднительном положении, потому что я не хочу удалять ни один из своих пакетов.
Есть ли какое-либо средство в такой ситуации, чтобы вернуть время молниеносного запуска?
Обновить:
Мы начали новый поток на emacs-devel
список рассылки о некоторых пластырей по Стефан Монье (описание этих патчей здесь ) , чтобы решить эту проблему. Любой желающий может проверить свои патчи и дать отзыв.
Еще одно обновление:
Похоже, что Стефан Моннье либо не заинтересован в этом вопросе, либо не получает мои сообщения. Я склонен верить первому, что хорошо, хотя я был бы признателен за какой-то ответ от него, если это так. Во всяком случае, код, который он создал для этой проблемы, пока работает довольно хорошо. Самые последние его патчи можно найти здесь (для Emacs 25.3) и здесь (для основной ветки Emacs).Благодаря его исправлениям я увидел хорошие улучшения во время запуска, и теперь я чувствую себя комфортно со временем запуска, так как оно максимально оптимизировано без потери возможностей моей настройки. Я надеялся, что эти патчи в какой-то момент попадут в магистраль Emacs, но я думаю, что мне (или кому-то еще) придется вместо этого взять факел вместо Стефана. У нас был небольшой спар в списке рассылки о передаче авторских прав и лицензировании. Сначала я чувствовал себя неловко, но из-за некоторых комментариев Ричарда Столлмана и других авторское право может быть не таким ограничительным, как я первоначально думал. Более того, для меня может быть возможность передать свои работы в общественное достояние в качестве альтернативы передаче авторских прав.
В любом случае, спасибо Стефану за патчи! Я надеюсь, что вы продолжите развивать эти изменения, но если нет, то все в порядке, и я могу продолжить развивать их в какой-то момент. Я также благодарю всех, кто предложил понимание и вклад в решение этой проблемы.
Еще одно обновление:
Ух ты, похоже, эта функция наконец-то появилась и будет в Emacs 27. Спасибо Стефану Моннье!
use-package
это способ пойти на это.Ответы:
Один из вариантов дизайна в package.el - попытаться сделать вещи «простыми». Часть этого заключается в том, что
package-initialize
ищет все пакеты, которые установлены, затем пытается выяснить, какие из них следует активировать (в зависимости от закрепления и недавности версий в случае, если доступно несколько версий одного и того же пакета), затем загружает каждый активировать<pkg>-autoloads.el
файл пакета .Таким образом, для N установленных пакетов это означает в основном чтение N
<pkg>-pkg.el
файлов описания пакетов и N<pkg>-autoloads.el
файлов. Для больших Ns это может стать серьезной проблемой. Другая потенциальная проблема производительности - добавление N элементовload-path
, поэтому каждый раз, когда вы,load
Emacs, будете искать в N каталогах, каждый изload
них замедляется.Есть несколько способов ускорить это:
Предоставьте какой-нибудь способ предварительного вычисления
~/.emacs.d/elpa/package-initialize.el(c)
файла, который будет результатом объединения всех прав<pkg>-autoloads.el
в правильном порядке. Затемpackage-initialize
можно просто загрузить этот файл, когда он есть, и пропустить все остальное. Затем вам понадобится какой-нибудь способ обновить / очиститьpackage-initialize.el(c)
файл, когда пакеты добавляются / обновляются / удаляются или когда вы меняете свойpackage-pinned-packages
или свойpackage-load-list
. Я думаю, что это можно сделать с помощью довольно небольшого количества изменений в системе (я думаю,package-initialize
что единственное, что действительно нужно было бы изменить, так это то, что его можно сказать «только активировать» без загрузки метаданных о доступных пакетах).Обеспечить некоторый способ создания / манипулирования суперпакетами, то есть пакетами, которые объединяют несколько пакетов в один (так что добавляется только один элемент
load-path
, загружается один<pkg>-pkg.el
и один<pkg>-autoloads.el
). Это может быть более трудным для выполнения (потому что тогда вы не можете активировать только часть пакетов, содержащихся в таких супер-пакетах, поэтому анализ зависимости / версии может быть сложным).Первый вариант, описанный выше, должен быть довольно простым для реализации и работать
package-initialize
намного быстрее, если у вас установлено много пакетов. Если вы заинтересованы в этом, не стесняйтесь обратиться ко мне за помощью.FWIW, я только что попытался создать такой файл мега-автозагрузки "вручную" на моей тестовой установке. Результаты: в то время как
package-initialize
загрузка занимает около 0,9 с, загрузкаmega-autoloads.el
файла занимает 0,3 с, что я могу уменьшить до 0,2 с, привязав letload-source-file-function
к nil, и до 0,1 с путем байтовой компиляции файла. Честно говоря, я ожидал лучшего ускорения, но оно того стоит.[EDIT] Этот подход "мега автозагрузки" теперь доступен в основной ветке Emacs (чтобы стать Emacs-27 в некотором отдаленном будущем). Это контролируется новой
package-quickstart
переменной.источник
package.el
разработчиков. Какой совет вы бы дали, начав с первого варианта? Я хотел бы посмотреть, что я могу с этим сделать, так как это кажется гораздо более работоспособным.<pkg>-autoloads.el
файлов только устанавливают автозагрузку и, в действительности, не заботятся о порядке, но ничто не мешает им делать другие случайные вещи, а package.el гарантирует, что пакет, от которого<pkg>
зависит, будет активирован раньше<pkg>
самого себя.Проблема, которую вы описываете из-за
package-initialize
того, что загружается так много времени, является хорошо известной. Это также одна из проблем, которую некоторые фреймворки emacs пытаются решить, загружая автозагрузки вручную.Я вижу два решения вашей проблемы.
Одним из главных доводов в пользу рекомендации DOOM emacs является то, что инфраструктура выводит управление пакетами за пределы emacs. Не поймите меня неправильно, управление пакетами по-прежнему выполняет emacs, просто управление пакетами выполняется вне стандартного пользовательского сеанса. Философия здесь такова: при нормальном запуске emacs мы должны предполагать, что все пакеты присутствуют и уже могут быть загружены. Это экономит много времени. DOOM Emacs обеспечивает своего рода эквивалент
apt-get
илиpacman
для Emacs. После того, как пакет установлен, при запуске emacs предполагается, что он уже установлен; никаких вопросов не было задано.источник