Технически, почему более эффективны процессы в Erlang, чем потоки ОС?

Характеристики Erlang

От программирования (2009) Erlang:

Параллелизм Erlang быстр и масштабируем. Его процессы легки в этом, виртуальная машина Erlang не создает поток ОС для каждого созданного процесса. Они создаются, планируются и обрабатываются в VM, независимом от базовой операционной системы. В результате время создания процесса имеет порядок микросекунд и независимо от количества одновременно существующих процессов. Сравните это с Java и C#, где для каждого процесса базовый поток ОС создается: Вы получите некоторые очень конкурентоспособные сравнения с Erlang, значительно превосходящим оба языка по характеристикам.

От Параллелизм ориентировал программирование в Erlang (PDF) (слайды) (2003):

Мы замечаем, что время, потраченное для создания процесса Erlang, постоянно 1µs до 2 500 процессов; после этого это увеличивается до приблизительно 3µs максимум для 30 000 процессов. Производительность Java и C# показывают наверху числа. Для небольшого количества процессов это сопровождает 300µs для создания процесса. Создание больше чем двух тысяч процессов невозможно.

Мы видим, что максимум для 30 000 процессов время для отправки сообщения между двумя процессами Erlang о 0.8µs. Для C# это сопровождает 50µs на сообщение до максимального количества процессов (который был приблизительно 1 800 процессами). Java был еще хуже максимум для 100 процессов, которые он сопроводил 50µs на сообщение после этого, он увеличился быстро до 10 мс за сообщение, когда было приблизительно 1 000 процессов Java.

Мои мысли

Я не полностью понимаю технически, почему процессы Erlang настолько более эффективны в порождении новых процессов и имеют намного меньшие объемы потребляемой памяти для каждого процесса. И ОС и Erlang VM должны сделать планирование, контекстные переключения, и отслеживать значения в регистрах и так далее...

Просто, почему потоки ОС не реализованы таким же образом как процессы в Erlang? Они должны поддерживать что-то больше? И почему им нужен больший объем потребляемой памяти? И почему у них есть более медленное порождение и коммуникация?

Технически, почему более эффективны процессы в Erlang, чем потоки ОС когда дело доходит до порождения и коммуникации? И почему не может потоки в ОС реализовываться и управляться тем же эффективным способом? И почему потоки ОС имеют больший объем потребляемой памяти плюс более медленное порождение и коммуникация?

Больше чтения

165
задан Philip Conrad 1 September 2013 в 05:42
поделиться

6 ответов

Есть несколько факторов:

  1. Erlang-процессы не являются процессами ОС. Они реализуются виртуальной машиной Erlang с использованием облегченной модели совместной работы с потоками (вытесняющей на уровне Erlang, но под контролем совместно запланированной среды выполнения). Это означает, что гораздо дешевле переключать контекст, потому что они переключаются только в известных, контролируемых точках и, следовательно, не должны сохранять все состояние ЦП (нормальное состояние, регистры SSE и FPU, отображение адресного пространства и т. Д.).
  2. Процессы Erlang используют динамически выделяемые стеки, которые начинаются с очень маленького размера и при необходимости увеличиваются. Это позволяет запускать многие тысячи - даже миллионы - процессов Erlang, не занимая всю доступную оперативную память.
  3. Erlang раньше был однопоточным, что означало, что не требовалось обеспечивать безопасность потоков между процессами. Теперь он поддерживает SMP, но взаимодействие между процессами Erlang в одном планировщике / ядре по-прежнему очень легкое (для каждого ядра есть отдельные очереди выполнения).
108
ответ дан 23 November 2019 в 21:09
поделиться

Поскольку интерпретатору Erlang нужно беспокоиться только о себе, у ОС есть много других вещей, о которых нужно беспокоиться.

1
ответ дан 23 November 2019 в 21:09
поделиться

Процессы Erlang соответствуют (приблизительно) зеленым потокам на других языках; между процессами нет разделения на принудительное использование ОС. (Вполне может быть принудительное разделение на языке, но это меньшая защита, несмотря на то, что Erlang работает лучше, чем большинство.) Поскольку они намного легче, их можно использовать гораздо шире.

С другой стороны, потоки ОС могут быть просто запланированы на разных ядрах ЦП и (в большинстве случаев) способны поддерживать независимую обработку с привязкой к ЦП. Процессы ОС похожи на потоки ОС, но с гораздо более сильным разделением, обеспечиваемым ОС. Цена этих возможностей в том, что потоки ОС и (тем более) процессы дороже.


Другой способ понять разницу заключается в следующем. Предположим, вы собираетесь написать реализацию Erlang поверх JVM (не особо безумное предложение), тогда вы должны сделать каждый процесс Erlang объектом с некоторым состоянием. Тогда у вас будет пул экземпляров потоков (обычно размер которых зависит от количества ядер в вашей хост-системе; это настраиваемый параметр в реальных средах выполнения Erlang, кстати), которые запускают процессы Erlang. В свою очередь, это распределяет работу, которая должна быть сделана, по реальным доступным системным ресурсам. Это довольно изящный способ делать что-то, но он полностью полностью полагается на тот факт, что каждый отдельный процесс Erlang мало что делает. Конечно, это нормально; Структура Erlang не требует, чтобы эти отдельные процессы были тяжелыми, поскольку программа выполняет их совокупность.

Во многом настоящая проблема заключается в терминологии. То, что Erlang называет процессами (и которые строго соответствуют той же концепции в CSP, CCS и, в частности, π-исчислении), просто не то же самое, что то, что языки с наследием C (включая C ++, Java, C # и многие другие) вызывают процесс или поток. Есть некоторые сходства (все они связаны с некоторым понятием одновременного выполнения), но определенно нет эквивалентности. Так что будьте осторожны, когда кто-то говорит вам «процесс»; они могут понять это как нечто совершенно иное…

32
ответ дан 23 November 2019 в 21:09
поделиться

После некоторых дополнительных исследований я нашел презентацию Джо Армстронга.

От Erlang - программное обеспечение для параллельного мира (презентация) (в 13 мин):

[Erlang] является параллельным языком — под этим я подразумеваю, что потоки являются частью языка программирования, они не принадлежат операционной системе. Это действительно то, что не так с языками программирования, такими как Java и C ++. Это потоки не на языке программирования, потоки — это что-то в операционной системе — и они наследуют все проблемы, которые у них есть в операционной системе. Одной из проблем является детализация системы управления памятью. Управление памятью в операционной системе защищает целые страницы памяти, поэтому наименьший размер потока — это наименьший размер страницы. Это на самом деле слишком много.

Если вы добавите больше памяти на свою машину — у вас будет такое же количество битов, которые защищают память, поэтому детализация таблиц страниц повышается вы в конечном итоге используете, скажем, 64 КБ для процесса, который, как вы знаете, выполняется в нескольких сотнях байт.

Я думаю, что он отвечает если не на все, то, по крайней мере, на некоторые из моих вопросов

68
ответ дан 23 November 2019 в 21:09
поделиться

Я реализовал сопрограммы на ассемблере и измерил производительность.

Переключение между сопрограммами, также известными как процессы Erlang, на современном процессоре занимает около 16 инструкций и 20 наносекунд. Кроме того, вы часто знаете, на какой процесс вы переключаетесь (пример: процесс, получающий сообщение в своей очереди, может быть реализован как прямая передача от вызывающего процесса к принимающему процессу), поэтому планировщик не вступает в игру, делая это операция O (1).

Чтобы переключить потоки ОС, требуется около 500-1000 наносекунд, потому что вы вызываете ядро. Планировщик потоков ОС может работать за время O (log (n)) или O (log (log (n))), что станет заметным, если у вас десятки тысяч или даже миллионы потоков.

Следовательно, процессы Erlang быстрее и лучше масштабируются, потому что и основная операция переключения выполняется быстрее, и планировщик работает реже.

46
ответ дан 23 November 2019 в 21:09
поделиться

Я думаю, Джонасу нужны были цифры по сравнению потоков ОС с процессами Erlang. Автор книги Programming Erlang Джо Армстронг некоторое время назад тестировал масштабируемость порождения процессов Erlang в потоки ОС. Он написал простой веб-сервер на Erlang и протестировал его на многопоточном Apache (поскольку Apache использует потоки ОС). Есть старый сайт с данными за 1998 год. Мне удалось найти этот сайт ровно один раз. Так что ссылку дать не могу. Но информация есть. Суть исследования показала, что Apache максимально обрабатывал чуть менее 8 тысяч процессов, в то время как его написанный от руки сервер Erlang обрабатывал более 10 тысяч процессов.

2
ответ дан 23 November 2019 в 21:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: