Emacs — легендарный текстовый редактор, обладающий невероятным набором возможностей и глубокой кастомизацией при помощи собственного диалекта Lisp — Elisp. За десятилетия своего существования Emacs превратился из простой утилиты в сложную экосистему, сочетающую в себе код на C и Lisp-интерпретатор. Однако с ростом функциональности возникла одна задача, выходящая за рамки обычной разработки — ускорение запуска программы. Как известно, запуск Emacs традиционно занимает значительное время, обусловленное загрузкой большого объема Elisp-кода и инициализацией соответствующего состояния. Для минимизации этой задержки была реализована технология dumper (также известная как unexec), позволяющая сохранить образ памяти с загруженным кодом на диск и быстро восстанавливать его при следующем запуске.
Благодаря этому процесс старта существенно ускорялся, значительно повышая удобство использования. Несмотря на свою эффективность, реализация dumper была технически непростой и глубоко интегрированной с особенностями операционной системы и библиотек. Суть технологии сводилась к тому, чтобы сделать снепшот процесса во время начальной загрузки и загружать этот моментальный снимок в оперативную память при последующих запусках. Но такие методы всегда сопровождаются плотной зависимостью от конкретных деталей, в данном случае — от функций и внутренних интерфейсов стандартной C-библиотеки GNU, glibc. В частности, Emacs сильно полагался на специфические low-level хуки, связанные с выделением памяти, которые обеспечивали сохранение и восстановление состояния heap.
В начале 2016 года разработчики glibc приняли решение обновить и модернизировать подсистему управления памятью, что предполагало удаление или изменение используемых хук-функций. Это изменило правила игры для Emacs: существующий механизм dumper потерял необходимую поддержку и перестал корректно работать со свежими версиями glibc. Обновленные библиотеки были уже несовместимы с подробной внутренней логикой unexec, что негативно сказалось на стабильности и производительности редактора. Помимо технических сложностей, эта ситуация вызвала серьезное разногласие внутри емкого комьюнити разработчиков Emacs, что стало известно как «спор вокруг Emacs dumper» 2016 года. Проблема оказалась гораздо глубже, чем казалось на первый взгляд.
Помимо потери glibc хуков, оказалось, что версия Emacs ранее 25.2 теряет стабильность, пытаясь применить устаревший интерфейс ralloc. По словам Эли Зарецкого, одного из соавторов и ведущих разработчиков Emacs, подобное поведение делает редактор практически непригодным для использования на современных системах GNU/Linux с новыми версиями glibc. Пользователи столкнулись с замедлением и повышенной нестабильностью программного обеспечения, что было особенно тревожным сигналом в условиях активного «редакторского противостояния» между Emacs и Vim. Очевидно, что ситуация требовала радикальных решений, поскольку в основе конфликта лежала устаревшая архитектура с сильной системной зависимостью, унаследованная из давно минувших времен.
Для перспективного развития Emacs было необходимо найти подход, который бы обеспечивал устойчивость, производительность и при этом был прост для сопровождения и развития. В этом контексте появилось предложение Дэниела Коласционе, которое получило название «portable dumper» — переносимый или портативный дампер. «Портативный дампер» представлял собой новую реализацию механизма загрузки изображения памяти, полностью написанную с нуля, которая обходилась без опасной и сложной зависимости от внутренних API glibc и любых низкоуровневых хаков. Вместо фиксирования внутреннего состояния malloc, разработчик решил сериализовать известные Эмпаксу Elisp-объекты в собственном формате, позволяющем эффективно их сохранять и загружать. При запуске новая версия могла маппить файл с дампом прямо в память и корректно инициализировать указатели, что приводило к результатам, практически не уступающим по производительности прежнему unexec, и даже обещало оптимизацию в будущем.
Кроме скорости и совместимости, новое решение сумело решить еще один важный вопрос безопасности — адресное пространство защищается механизмами современного ОС, такими как ASLR. Текущая система unexec требовала отключения ASLR, что ослабляло защиту программного кода и данных от атак. В новой системе позволялось сохранять преимущества ASLR, хотя оптимизация для быстрой загрузки заключалась в том, чтобы фиксировать адрес маппинга образа. Это вызвало детальное обсуждение потенциальных уязвимостей, ведь ещё оставалась возможность выполнения вредоносного Elisp-байткода из памяти. В итоге компромисс предполагал по умолчанию отключать фиксированный маппинг, сохраняя защитные свойства ОС.
Именно этот объемный патч вызвал наибольшие споры в сообществе. Зарецкий резко критиковал идею ввода огромного объема нового C-кода, который усложнит поддержку проекта. Его аргумент заключался в том, что число разработчиков, способных работать с низкоуровневыми деталями ядра Emacs на C все уменьшается, и нужно стремиться к упрощению архитектуры, чтобы поддерживать активное развитие проекта. Он предлагал сосредоточиться на ускорении непосредственного загрузчика Elisp-кода без необходимости в сложных дамперах. Сторонники portable dumper в ответ указывали на то, что реально работающая, активно поддерживаемая и современная система лучше, чем отсутствие решения.
Сам Коласционе и другие ведущие участники, включая Ричарда Столлмана и Джона Вигли, были склонны принять новый модуль, понимая, что это значительно облегчит поддержку Emacs и устранит критические проблемы совместимости. Конфликт дошел до того, что Зарецкий пригрозил уйти с позиции со-сопредсатавляющего проекта, если будет принято решение о принятии portable dumper. Угроза всколыхнула сообщество, вызвав бурное обсуждение, однако большинство участников по-прежнему считало, что изменения необходимы. Несмотря на внутренние разногласия, дух сообщества Emacs показал готовность пройти через эту боль в попытках сохранить жизнеспособность редактора в новых условиях. Этот спор — показатель сложности, с которыми сталкиваются крупные открытые проекты с обширным историческим багажом.
Проблема Emacs dumper — это не просто технический баг, а вопрос о том, как совмещать производительность, безопасность и удобство сопровождения в коде, который к тому же часто работает с системными механизмами операционной системы. Кроме того, конфликт обнажил кадровый дефицит опытных разработчиков на языке C внутри сообщества, а также сложность поддержки двух языков — C и Lisp — в одном теле проекта. В середине 2010-х годов вопросы ускоренного старта стали все более важными не только для Emacs, но и для широкого круга программных продуктов. Все большее значение приобретали технологии предкомпиляции, джит-компиляции и сериализации состояния. В сравнении, работа с дампами памяти, как это было в Emacs, становилась анахронизмом, который требовал пересмотра.
Еще одним интересным аспектом дела было отношение к альтернативным методам ускорения запуска, например, использование серверного режима Emacs. В этом режиме редактор запускается как демон, и пользовательские клиенты подключаются к нему, что позволяет быстро открывать новые окна без полной загрузки. Однако такое решение не оказалось универсальным: оно не решало проблемы долгой загрузки при первоначальном запуске или во время массовой перекомпиляции Elisp-кода, которая часто встречается при сборке. В целом, споры вокруг Emacs dumper 2016 года стали важной вехой в истории развития редактора. Они наглядно показали переход от унаследованных от прошлого технических подходов к более современным, переносимым и масштабируемым методам.
Кроме того, конфликт позволил сообществу сфокусироваться на улучшении безопасности, поддерживаемости и гибкости кода. Все эти события остаются актуальными для современных разработчиков Emacs и тех, кто интересуется эволюцией программного обеспечения с длительной историей. Для многих пользователей и специалистов этот эпизод олицетворяет сложности поиска баланса между инновациями и сохранением стабильности в больших проектах с открытым исходным кодом, подчеркивая важность обсуждения, компромиссов и постоянного развития.