О преимуществах Erlang
Юрий Жлоба, Минск, Belarus
LVEE 2012
Erlang was created not as a general-purpose language, but for telecom domain where application should serve huge amount of clients, be fault-tolerant, continue working whatever happens and be updated while serving clients.
Despite the fact that many new languages were created after Erlang, including such popular ones as Java and .NET, Erlang is still in demand, and today even more than ever.
Features making Erlang so good are described, as well as why it is better than any other language for high-load, distributed, fault-tolerant systems.
Чуть-чуть истории, это важно :)
Erlang не создавался как язык общего назначения, он создавался для довольно специфичной предметной области — для телекомов. Люди в компании Ericsson, и менеджеры, принимавшие отвественные решения, и инженеры, работавшие над языком, были прагматиками и точно знали, чего хотели. Они хотели:
- обслуживать очень большое количество клиентов;
- быть устойчивым к ошибкам, продолжать работать, чтобы ни случилось;
- обновлять систему не прекращая обслуживать клиентов;
Поэтому в Erlang на уровне дизайна языка заложены:
- эффективная реализация многопоточности (Concurrency);
- устойчивость к ошибкам (Fault Tolerance);
- распределенность (Distributed Computation);
- горячее обновление (Dynamic Code Loading);
Erlang сразу хорошо показал себя на практике во внутренних проектах Ericsson. Конкурировать ему приходилось в основном с С++, и Erlang легко выигрывал эту конкуренцию. Но тут появилась Java и быстро захватила умы разработчиков и менеджеров. В т.ч. умы менеджеров Ericsson. Они попробовали Java, и оказалось, что для их задач Erlang все равно лучше :)
Примерно до 2006 года Erlang был малоизвестным языком, который за пределами компании Ericsson использовался очень мало. А в 2006 году произошла важная вешь — производители процессоров уперлись в потолок при наращивании тактовых частот и стали наращивать производительность за счет добавления ядер процессоров. Что сделало многопоточное программирование очень актуальным и заставило IT мир обратить внимание на языки, умеющие эффективно распаралеливать выполнение на несколько процессоров. В т.ч. и на Erlang.
Причем реализация многопоточности в Erlang оказалась настолько эффективной, что ее охотно компировали в другие языки, например Scala и Go.
Сравнение виртуальных машин Java и Erlang
Для Scala и Java была создана библиотека AKKA, реализующая многопоточность на основе Message Passing, примерно так же, как в Erlang. Значит ли это, что теперь на этих языках можно создавать такие же эффективные многопоточные проекты, как на Erlang? Увы нет. Ибо есть важные различия на уровне виртуальных машин, которые никакими библиотеками нельзя компенсировать.
JVM использует потоки операционной системы, которые являются довольно сложными и относительно ресурсоемкими сущностями. Создание потока, удаление потока, переключение между потоками — все это происходит относительно долго. Нельзя создать сколько угодно много потоков, их количество лимитировано имеющейся оперативной памятью.
Виртуальная машина Erlang имеет собственную реализацию очень легковестных потоков, работающих поверх потоков операционной системы. Они очень быстро создаются, удаляются, переключаются, и используют очень мало ресурсов. Поэтому их можно создавать очень много — десятки и сотни тысяч в одном приложении.
И из этого следуют важные архитектурные различия JVM и Erlang проектов. Сервер, написанный на Java, не может себе позволить создавать отдельный поток на обслуживание каждого клиентского запроса. Приходится решать сложную архитектурную задачу, распределяя запросы по пулу заранее созданных процессов. Сервер, написанный на Erlang, может создавать поток для каждого запроса. И два потока, если надо :)
Кроме этого, в виртуальных машинах сильно отличаются сборщики мусора. Сборка мусора в Java, несмотря на многолетние оптимизации, все-таки существенно замедляет работу приложения в те моменты, когда она работает. В Erlang сборщик мусора свой у каждого потока. Вместо одного большого сборщика, очищающего всю память приложения, работают много мелких сборщиков, очищающих небольшие участки памяти. И этот нюанс опять ведет к важным последствиям:
- Они не работают все одновременно, а каждый отдельно, в разные моменты времени;
- Небольшой участок памяти очищается быстрее, чем большой;
- Среди всех процессов много таких, которые потребляют мало памяти. Их сборщики вообще никогда не запускаются;
В итоге сборка мусора в виртуальной машине Erlang не оказывает заметного влияния на производительность :)
Текст тезисов доступен под лицензией Creative Commons Attribution-ShareAlike 3.0.