Хабрахабр

[Перевод] Гниение программного обеспечения

В книге «Электромагнитная эпоха: работа, любовь и жизнь, когда роботы правят миром» Робин Хэнсон кратко обсуждает программную гниль:

Но оно медленно изменяется, чтобы справиться с постоянным потоком новых задач, инструментов и ситуаций. Программное обеспечение изначально было разработано для одного набора задач, инструментов и ситуаций. В конце концов, лучше начать всё сначала и написать с нуля новые подсистемы, а иногда и полностью новые системы. Такой софт становится более сложным, хрупким, в него труднее вносить полезные изменения (Леман и Биледи, 1985)1.

Я уверен, что это правда. Как правило, грамотная адаптация программного обеспечения к новым условиям занимает больше времени и усилий, чем написание нового программного обеспечения с нуля. Программисты не любят признавать это, но доказательства очевидны. В проектах open source есть несколько известных примеров.
Изначально Mozilla Firefox запускал все задачи в одном процессе. После выхода Google Chrome стало ясно, что модель с несколькими процессами повышает безопасность и производительность. Вскоре разработчики Mozilla начали планировать, как реализовать в Firefox многопроцессность. Это было в 2007 году.

Эта задержка произошла вовсе не от недостатка желания. Почти десять лет спустя Mozilla, наконец, выпустила мультипроцессный Firefox на массовую аудиторию. Тем не менее, Chrome был написан с нуля за гораздо меньшее время, чем потребовалось Firefox для изменения. У Mozilla талантливые и целеустремленные разработчики. У этого две основные причины:

  • Переделка однопроцессной архитектуры в многопроцессную предполагает множество мелких изменений. Некоторые вызовы функций нужно заменить межпроцессными коммуникациями. Общее состояние нужно обернуть в мьютексы. Кэши и локальные БД должны поддерживать параллельный доступ.
  • Firefox должен сохранить совместимость с существующими расширениями (или заставить разработчиков их обновить). Chrome создавал API для расширений с нуля, не имея таких ограничений.

Но ситуация ещё хуже. Ограничения противоречат друг другу: нужно перестроить внутреннюю архитектуру, но оставить почти без изменений общедоступные API. Неудивительно, что Mozilla понадобилось десять лет на такой подвиг.
Изначально Apache httpd работал по модели «один процесс на соединение». Один процесс прослушивал порт 80, затем делал accept() и fork(). Дочерний процесс потом выполнял read() и write() на сокете. Когда запрос завершён, дочерний процесс закрывал сокет close() и выполнял exit().

Она абсолютно ужасна для производительности, особенно при обработке долгоживущих соединений. Такая архитектура простая, лёгкая в реализации на многих платформах и… всё. И вскоре Apache перешёл на потоковую модель, которая улучшила производительность. Справедливости ради: это был 1995 год. Архитектура «один поток на соединение» требует 1000 потоков для обслуживания 1000 одновременных подключений. Тем не менее, он не мог обрабатывать 10 000 одновременных соединений. Это отнимает время. У каждого потока собственный стек и состояние, его должен запланировать и запустить шедулер операционной системы.

Это позволило обрабатывать больше одновременных соединений и сделало его невосприимчивым к атакам Slowloris. Напротив, Nginx с самого начала использовал шаблон реактора.

За несколько лет до выхода Nginx разработчики Apache начали перепроектировать httpd для улучшения производительности. Nginx вышел в 2007 году, и его преимущество в производительности было очевидным. 2 в 2005 году. Многопроцессный модуль event вышел с Apache 2. Хуже всего, что он сломал совместимость с популярными модулями, такими как mod_php. Но обнаружились проблемы совместимости. 4 вышел с этим модулем (MPM) по умолчанию. Проблему не могли исправить до 2012 года, когда Apache 2. Вместо шаблона реактора Apache использовал отдельные пулы потоков для прослушивания/приёма соединений и обработки запросов. Хотя он работал гораздо лучше, чем предыдущий prefork и MPM-воркер, но так и не смог сравняться по производительности с Nginx. Архитектура примерно эквивалентна запуску балансировщика нагрузки или обратного прокси перед воркером MPM httpd2.

Python — хороший язык программирования. Он выразителен, прост в освоении (по крайней мере, для языка программирования) и поддерживается на разных платформах. Но в течение последних двух десятилетий у самой популярной реализации Python была серьёзная проблема: она не могла легко воспользоваться преимуществами нескольких процессорных ядер.

Из питоновского вики: Причина в глобальной блокировке интерпретатора или GIL.

Такая блокировка необходима главным образом потому, что управление памятью CPython не является потокобезопасным. В CPython глобальная блокировка интерпретатора — это мьютекс, который блокирует одновременное выполнение нескольких потоков кода. (Но поскольку GIL существует, другие функции стали зависеть от него).

Первоначально GIL не представлял особой проблемы. При создании Python многоядерные системы встречались редко. А GIL было легко написать и это простая, логичная система. Но сегодня многоядерные процессоры работают даже в наручных часах. GIL — очевидный и вопиющий дефект во всех отношениях приятного языка. Несмотря на популярность CPython, несмотря на талантливых разработчиков, несмотря на спонсоров, таких как Google, Microsoft и Intel, исправлять GIL даже не планируется.
Даже при наличии талантливых инженеров, большого количества денег и чёткого плана зрелое программное обеспечение чрезвычайно трудно изменить. Я пытался найти случаи, которые опровергают гниение ПО, но их, похоже, не существует. Робин Хэнсон попросил привести контрпримеры, но никто не предложил ничего убедительного. Есть много старых программных проектов, но им не пришлось особо адаптироваться. Я реально хочу найти хорошие контрпримеры, потому что без них создаётся слишком мрачная картина перспектив программного обеспечения.

Дополнительные материалы

1. Цитата из статьи «Эволюция программ: процессы изменения программного обеспечения». Работа старше меня, и я не могу найти онлайн-версию. Я купил физическую копию и с трудом осилил её. Терминология странная, но выводы не слишком удивительны. ↑

Любой, кто знает устройство httpd, возразит против такого сравнения, но здесь мы жертвуем точностью ради краткости. 2. ↑ Прошу прощения за это.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть