Как/почему делают функциональные языки (конкретно Erlang) масштабируются хорошо?

Ответ, который дал @lzap, является хорошим решением. Однако я хотел бы добавить, что вы должны добавить. путь к классу, так что ваш текущий каталог не будет оставлен, в результате ваши собственные классы будут опущены. Это случилось со мной на некоторых платформах. Таким образом, обновленная версия для JUnit 4.x будет:

java -cp .:/usr/share/java/junit.jar org.junit.runner.JUnitCore [test class name]
88
задан David Locke 23 January 2009 в 21:31
поделиться

8 ответов

Функциональный язык (в целом) не полагается на видоизменение переменной. Из-за этого мы не должны защищать "общее состояние" переменной, потому что значение фиксируется. Это в свою очередь избегает большинства обруча, переходящего, что традиционные языки должны пойти до реализации алгоритм через процессоры или машины.

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

то, Что это означает, - то, что программист является (номинально) беззаботным, что сообщение будет обработано на другом процессоре или машине: просто отправка сообщения достаточно хороша для него для продолжения. Если это будет заботиться об ответе, это будет ожидать его как другое сообщение .

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

Контраст это с традиционной системой: мы должны поместить взаимные исключения и семафоры вокруг "защищенных" переменных и выполнения кода. У нас есть трудная привязка в вызове функции через стек (ожидающий возврата для появления). Все это создает узкие места, которые являются меньшим количеством проблемы в общем ничто система как Erlang.

РЕДАКТИРОВАНИЕ: Я должен также указать, что Erlang является асинхронным. Вы отправляете свое сообщение, и возможно/когда-нибудь другое сообщение возвращается. Или нет.

точка Spencer об исполнении с изменением последовательности также важна и хорошо отвечена.

95
ответ дан MinhTri 5 November 2019 в 15:04
поделиться

Система очереди сообщений прохладна, потому что она эффективно производит "fire-and-wait-for-result" эффект, который является синхронной частью, о которой Вы читаете. Что делает, это невероятно потрясающее - то, что это означает, что строки не должны быть выполнены последовательно. Рассмотрите следующий код:

r = methodWithALotOfDiskProcessing();
x = r + 1;
y = methodWithALotOfNetworkProcessing();
w = x * y

Полагают на мгновение, что methodWithALotOfDiskProcessing () занимает приблизительно 2 секунды для завершения и что methodWithALotOfNetworkProcessing () занимает приблизительно 1 секунду для завершения. На процедурном языке этот код занял бы приблизительно 3 секунды для выполнения, потому что строки будут выполняться последовательно. Мы напрасно тратим время, ожидая одного метода для завершения, который мог работать одновременно с другим, не конкурируя за единственный ресурс. На функциональном языке строки кода не диктуют, когда процессор будет делать попытку их. Функциональный язык попробовал бы что-то как следующее:

Execute line 1 ... wait.
Execute line 2 ... wait for r value.
Execute line 3 ... wait.
Execute line 4 ... wait for x and y value.
Line 3 returned ... y value set, message line 4.
Line 1 returned ... r value set, message line 2.
Line 2 returned ... x value set, message line 4.
Line 4 returned ... done.

, Насколько прохладный это? Путем продолжения кода и только ожидания, в случае необходимости мы уменьшили время ожидания до двух секунд автоволшебно!: D Так да, в то время как код синхронен, он имеет тенденцию иметь различное значение, чем на процедурных языках.

РЕДАКТИРОВАНИЕ:

, Как только Вы схватываете это понятие в сочетании с сообщением Godeke, которое легко вообразить, как простой это становится для использования в своих интересах нескольких процессоров, ферм сервера, избыточных хранилищ данных и кто знает что еще.

72
ответ дан Spencer Ruport 5 November 2019 в 15:04
поделиться

Вероятно, что Вы перепутываете синхронный с последовательный .

тело функции в erlang обрабатывается последовательно. Таким образом, то, что Spencer сказал об этом "автоволшебном эффекте", не сохраняется для erlang. Вы могли смоделировать это поведение с erlang все же.

, Например, Вы могли породить процесс, который вычисляет количество слов в строке. Поскольку у нас есть несколько строк, мы порождаем один такой процесс для каждой строки и получаем ответы для вычисления суммы от него.

Тот путь, мы порождаем процессы, которые делают "тяжелые" вычисления (использующий дополнительные ядра при наличии), и позже мы собираем результаты.

-module(countwords).
-export([count_words_in_lines/1]).

count_words_in_lines(Lines) ->
    % For each line in lines run spawn_summarizer with the process id (pid)
    % and a line to work on as arguments.
    % This is a list comprehension and spawn_summarizer will return the pid
    % of the process that was created. So the variable Pids will hold a list
    % of process ids.
    Pids = [spawn_summarizer(self(), Line) || Line <- Lines], 
    % For each pid receive the answer. This will happen in the same order in
    % which the processes were created, because we saved [pid1, pid2, ...] in
    % the variable Pids and now we consume this list.
    Results = [receive_result(Pid) || Pid <- Pids],
    % Sum up the results.
    WordCount = lists:sum(Results),
    io:format("We've got ~p words, Sir!~n", [WordCount]).

spawn_summarizer(S, Line) ->
    % Create a anonymous function and save it in the variable F.
    F = fun() ->
        % Split line into words.
        ListOfWords = string:tokens(Line, " "),
        Length = length(ListOfWords),
        io:format("process ~p calculated ~p words~n", [self(), Length]),
        % Send a tuple containing our pid and Length to S.
        S ! {self(), Length}
    end,
    % There is no return in erlang, instead the last value in a function is
    % returned implicitly.
    % Spawn the anonymous function and return the pid of the new process.
    spawn(F).

% The Variable Pid gets bound in the function head.
% In erlang, you can only assign to a variable once.
receive_result(Pid) ->
    receive
        % Pattern-matching: the block behind "->" will execute only if we receive
        % a tuple that matches the one below. The variable Pid is already bound,
        % so we are waiting here for the answer of a specific process.
        % N is unbound so we accept any value.
        {Pid, N} ->
            io:format("Received \"~p\" from process ~p~n", [N, Pid]),
            N
    end.

И это - то, на что похоже, когда мы выполняем это в оболочке:

Eshell V5.6.5  (abort with ^G)
1> Lines = ["This is a string of text", "and this is another", "and yet another", "it's getting boring now"].
["This is a string of text","and this is another",
 "and yet another","it's getting boring now"]
2> c(countwords).
{ok,countwords}
3> countwords:count_words_in_lines(Lines).
process <0.39.0> calculated 6 words
process <0.40.0> calculated 4 words
process <0.41.0> calculated 3 words
process <0.42.0> calculated 4 words
Received "6" from process <0.39.0>
Received "4" from process <0.40.0>
Received "3" from process <0.41.0>
Received "4" from process <0.42.0>
We've got 17 words, Sir!
ok
4> 
15
ответ дан Chris Czura 5 November 2019 в 15:04
поделиться

Ссылочная прозрачность: См. http://en.wikipedia.org/wiki/Referential_transparency_ (computer_science)

2
ответ дан Jon Ericson 5 November 2019 в 15:04
поделиться

Ключевая вещь, которая позволяет Erlang масштабироваться, связана с параллелизмом.

операционная система обеспечивает параллелизм двумя механизмами:

  • процессы операционной системы
  • потоки операционной системы

Процессы не совместно используют состояние †“один процесс, не может разрушить другого дизайном.

доля Потоков указывает, что †“один поток может разрушить другого дизайном †“, это - Ваша проблема.

С Erlang †“один процесс операционной системы используется виртуальной машиной, и VM предоставляет параллелизм программе Erlang не при помощи потоков операционной системы, а путем обеспечения Erlang обрабатывает †“, который является реализациями Erlang его собственный timeslicer.

Эти Erlang процесс говорят друг с другом путем отправки сообщений (обработанный Erlang VM не операционная система). Процессы Erlang обращаются друг к другу использующему идентификатор процесса (PID), который имеет трехчастный адрес <<N3.N2.N1>>:

  • процесс № N1 на
  • VM N2 на
  • реальная машина N3

Два процесса на том же VM, на различном VM's на той же машине или двух машинах связываются таким же образом †“Ваше масштабирование, поэтому независимо от количества реальных машин, Вы развертываете свое приложение на (в первом приближении).

Erlang только ориентирован на многопотоковое исполнение в тривиальном смысле †“, он не имеет потоков. (Язык то есть, использование VM SMP / многоядерное использование VM один поток операционной системы на ядро).

12
ответ дан hcs42 5 November 2019 в 15:04
поделиться

Сообщения Erlang являются чисто асинхронными, если Вы хотите синхронный ответ на свое сообщение, необходимо явно кодировать для этого. То, что было возможно сказано, было то, что сообщения в окне сообщения процесса обрабатываются последовательно. Любое сообщение, отправленное в процесс, идет, находится в том окне сообщения процесса, и процесс добирается для выбора одного сообщения от того поля, обрабатывают его и затем идут дальше к следующему, в порядке это считает целесообразным. Это - очень последовательное действие, и получить блок делает точно это.

Похож на Вас, перепутали синхронный и последовательный как chris упомянутый.

3
ответ дан Jebu 5 November 2019 в 15:04
поделиться

На чисто функциональном языке порядок оценки не имеет значения - в функциональном приложении fn (arg1.. argn), n аргументы могут быть оценены параллельно. Это гарантирует высокий уровень (автоматического) параллелизма.

Erlang использует модель процесса, куда процесс может работать в той же виртуальной машине, или на различном процессоре - нет никакого способа сказать. Это только возможно, потому что сообщения копируются между процессами, нет никакого общего (изменяемого) состояния. Многопроцессорный параллелизм идет намного дальше, чем многопоточность, так как потоки зависят от общей памяти, это там может только быть 8 потоками, работающими параллельно на 8 ядрах процессора, в то время как многопроцессорная обработка может масштабироваться к тысячам параллельных процессов.

-1
ответ дан mfx 5 November 2019 в 15:04
поделиться

У Вас может быть неверное толкование того, как Erlang работает. Время выполнения Erlang минимизирует контекстное переключение на ЦП, но если существует несколько доступных центральных процессоров, то все используются для обработки сообщений. У Вас нет "потоков" в том смысле, что Вы делаете на других языках, но у Вас может быть много сообщений, обрабатываемых одновременно.

6
ответ дан Kristopher Johnson 5 November 2019 в 15:04
поделиться
Другие вопросы по тегам:

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