Решил немного помечтать и вообразить, что нужно SXEmacs, чтобы выиграть приз «Лучший программный продукт года». Было ли вообще такое, чтобы GNU Emacs выигрывал этот приз? Что же необходимо изменить и сделать в SXEmacs, чтобы это событие произошло?
- Кардинально улучшить подсистему обработки событий (event loop).
- Реализовать подсистему отображения (redisplay) используя современные средства, например Cairo. Использовать современные библиотеки виджетов, например GTK+.
- Реализовать нормальную мультиязыковую поддержку.
- Поймать все утечки памяти при использовании BDWGC и сделать его сборщиком мусора по умолчанию.
- Реализовать чистую интеграцию различных ЯП, таких как Python, Ruby и др.
- Улучшить документацию как для разработчиков так и для пользователей.
- Создать более продвинутый и быстрый сопоставитель текста с образцом на замену регулярных выражений. На базе него сделать, чтобы font-lock работал корректно и быстро.
- Создать систему совместной разработки на базе SXEmacs.
info
Призываю читателей к дискуссии. Опишите свой взгляд, расскажите каким вы хотели бы видеть ([S]X)Emacs.
Подробное изложение каждой части этого плана я буду публиковать отдельными постами (не обязательно в правильном порядке). Потом их можно будет склеить в одну статейку и оформить как некий путь развития SXEmacs. Сегодня будет небольшой обзор подсистемы событий.
Подсистема событий
Самое удивительное, что сейчас вообще нет этой подсистемы ;). Есть определённые части, выполняющие необходимые действия, но отсутствует целостность, расширяемость и сила. В существующей ПС есть только высокий уровень доступа, нет разделения API на низкий/высокий уровни, поэтому если требуется что-то добавить, то необходимо делать много низкоуровневой мишуры, с помощью копи&паст программирования — утомительно.
В SXEmacs было решено использовать libev как низкоуровневую базу для ПС. Выбор стоял между liboop, libevent, libev и одной проприетарной библиотекой, которую планировалось перелицензировать (уже было получено согласие правообладателя). liboop отпала первой — библиотека практически мертва. libevent является почти de-facto стандартом для создания софта с ПС, но у нескольких разработчиков SXEmacs был негативный (как и позитивный тоже) опыт использования libevent и как раз ограничения, которые существуют в ней плюс просто ошеломляющие результаты тестирования скорости libev в сравнении с libevent не позволили выбрать libevent. Проприетарная библиотека отпала так как она зависела от дополнительной большой библиотеки, а так же в ней не очень удобный API (хотя, видимо, очень мощный) и отсутствовала документация.
Так зачем вообще всё это нужно? А для того, чтобы полностью избавиться от внутренних блокировок в SXEmacs. Блокировки бывают двух типов:
- Выполнение elisp кода приостанавливается в ожидании какого-то события.
- Блокирует сам вызов библиотечной функции.
К пункту 2 относятся вызовы для разрешения DNS имён, такие как gethostbyname(3) и getaddrinfo(3), вызов connect(2), а также, как это не удивительно, вызов write(2). В GNU Emacs реализован неблокирующий вызов connect если передано ключевое слово :nowait1 в процедуру make-network-process, при этом вызов make-network-process всё же может заблокировать, если заблокировало разыменование имени хоста. В SXEmacs вызов connect всегда блокирует, поэтому open-network-stream всегда блокирует. Что касается write(2), то по настоящему всё же write не блокирует, ибо дескриптор был переведён в неблокирующий режим для неблокирующего чтения, но все Емаксы, получая EWOULDBLOCK от write(2), делают select в ожидании, когда разрешат записать.
К пункту 1 относятся любые вызовы accept-process-output и call-process. Что произойдёт если accept-process-output ожидает данных и в этот момент приходит какое-нибудь событие? Если событие системное, то оно обрабатывается немедленно, если событие специальное или командное2, то оно будет отложено и записано в очередь событий, которые будут обработаны позже.
Асинхронный обработчик событий
В SXEmacs есть такая вещь называется ASYNEQ — это возможность асинхронной обработки событий. Не всякое событие может быть обработано асинхронно. В общем случае асинхронная обработка командных событий ведёт к условиям гонки (race condition)3. Специальные же события без проблем можно обрабатывать асинхронно. Именно по этой причине xlib и xwem работают более предсказуемо под SXEmacs, ибо они порождают просто тонны специальных событий, которые в XEmacs обрабатываются синхронно как и командные.
Часто командные события всё же можно обрабатывать асинхронно. Условия гонки были обнаружены токмо спустя год после того как в SXEmacs появился ASYNEQ. Это говорит о том, что условия гонки крайне редки и сильно зависят от специфики elisp кода, то есть автоматически невозможно определить возникнет ли в конкретном случае race condition или нет. Возможно, необходимо определить переменную asyneq-ignore-command-events, которую можно связать со значением t в особых случаях, когда необходимо запретить асинхронную обработку командных событий.
Как организовать новую ПС
Что мы хотим от новой ПС:
- Целостность — одно место обработки событий, отсутствие костылей на вроде как при потенциальном блокировании write в process-send-string
- Простой и мощный API как с низкоуровневыми, так и с высокоуровневыми конструкциями
- Возможность интеграции других подсистем событий в ПС SXEmacs. Для начала X11 и Glib
Использовать новую ПС будут:
- На низком уровне
- Асинхронное разыменование DNS
- Остальные потенциально блокирующие вызовы
- Клей для других ПС
- На высоком уровне
- Event API на elisp уровне
- Таймеры
- Прогнозируемые предикаты
- И т.д.
Попробую изобразить в виде схемы, что будет происходить при возникновении командного события, которое порождает вызов open-network-stream. Как видим, событие помещается в очередь событий и когда до него дойдёт очередь, оно будет обработано, что породит вызов процедуры open-network-stream, которой, в свою очередь, необходимо разыменовать имя хоста и подсоединиться к нему, т.е. произвести две потенциально блокирующих операции. За время выполнения open-network-stream мы два раза посетим обработчик событий и в случае, если нам действительно нужно будет ждать, мы сможем обработать ещё кучу событий из очереди.
Именно так я и вижу работу новой ПС в SXEmacs.
4 комментария:
ну второй, третий и предпоследний пункты есть в gnu emacs.
насчет поддержки разных языков - я все-таки надеюсь на работы, ведущиеся в рамках cedet
А что, GNU Emacs разве умеет использовать Cairo для redisplay? Я думал там только виджеты GTKшные поддерживаются
насчёт предпоследнего можно по подробней? Что это за механизм?, даёт ли он O(N) скорость? Я сомневаюсь, что в Emacs сделают regexpы со скоростью O(M*N), где M - длина регекспа, а N - длина входа .. хотя документов о том как это сделать предостаточно
вообще как раз про предпоследний пункт я и хочу написать в след раз как продолжение серии bsoy .. там и можно будет обсудить все перипетии
насколько я помню - вроде делали поддержку Cairo. В 23-й версии переписали display часть, так что шрифты теперь смотрятся хорошо. Плюс народ вел работу над gtkembed, что позволяло ембедидить практически любые Х-вые программы.
Насчет регекспов. При переходе на 22-ю версию, regex engine был полностью переписан, что дало очень сильное увеличение быстродействия, и фонт-лок сейчас работает совсем незаметно, даже на огромных исходниках
отлично! быстрые регекспы это правильно!
хорошие изменения, нужно будет поковырять GNU Emacs 23 на досуге
Отправить комментарий