Насколько тяжелы события erlang против потоков? - PullRequest
4 голосов
/ 07 октября 2011

Не уверен, если это целесообразно, но я читаю на erlang, и я смотрел на gen_event, и мне было интересно, какова нагрузка при использовании его для полного событийно-ориентированного программирования, как я бы использовал в Node.Js дляпример.

Каковы издержки при обработке события обработчиком задачи против создания нового потока в erlang для выполнения той же задачи.

Спасибо.

1 Ответ

8 голосов
/ 07 октября 2011

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

Так что не бойтесь порождать процесс для обработки каждого из запросов, которые вы хотите обслуживать в вашей системе - это хороший начальный дизайн, который обычно обеспечивает хорошую пропускную способность за счет параллелизма и имеет тенденцию масштабироваться до большего количества ядер./ cpus / node легче.

Дополнительным преимуществом является то, что код в каждом процессе может быть написан простым процедурным способом:

%% Ask a server to perform a request and await the response from the worker.
request(Server, R) ->
    Server ! {new_request, R, self()},
    receive {response, Response} -> Response end.

%% Create a server.
start() ->
    spawn(?MODULE, server, []).

%% The server code
server() ->
    receive
        {new_request, R, Sender} ->
            %% Spawn a process to handle this request
            spawn(?MODULE, process_request, [R, Sender]),
        server()
    end.

%% The worker code
process_request(R, Sender) ->
    A = do_io(),
    B = do_cpu_bound_thing(A),
    C = do_io(C),
    Sender ! {response, C}. % Return the response to the sender
    %% Process shuts down cleanly here as there's nothing more to do. 

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

Отсюда легко добавить контроль рабочих процессов, чтобы мы моглиперезапустите отдельные запросы, которые не выполняются, распределенная обработка на нескольких машинах, добавив аргумент 'Node' к вызову spawn, чтобы создать рабочих, тайм-ауты, чтобы клиенты, выполняющие запросы, не блокировались навсегда, если сервер перегружен или рабочий процесс завершился неудачей, и т.д.on.

Вы не можете получить параллелизм, на который способен вышеуказанный код, используя несколько обработчиков внутри процесса gen_event.Код gen_event будет более сложным для чтения, и вам придется самостоятельно чередовать запросы, а не позволять среде выполнения делать это за вас.


tl; dr: накладные расходы настолько малы, а другие преимущества таковызамечательно, что вы обычно (почти всегда) порождаете процесс, а не пытаетесь делать несколько вещей одновременно в процессе gen_event.

...