Características de Erlang
Da Programação Erlang (2009):
A simultaneidade de Erlang é rápida e escalável. Seus processos são leves, pois a máquina virtual Erlang não cria um encadeamento do SO para cada processo criado. Eles são criados, agendados e manipulados na VM, independentemente do sistema operacional subjacente. Como resultado, o tempo de criação do processo é da ordem de microssegundos e independente do número de processos existentes simultaneamente. Compare isso com Java e C #, onde para cada processo é criado um encadeamento do SO subjacente: você obterá comparações muito competitivas, com o Erlang superando muito as duas linguagens.
Da programação orientada à concorrência em Erlang (pdf) (slides) (2003):
Observamos que o tempo necessário para criar um processo Erlang é constante de 1µs a 2.500 processos; depois disso, aumenta para cerca de 3 µs para até 30.000 processos. O desempenho do Java e C # é mostrado na parte superior da figura. Para um pequeno número de processos, são necessários cerca de 300 µs para criar um processo. Criar mais de dois mil processos é impossível.
Vemos que, para até 30.000 processos, o tempo para enviar uma mensagem entre dois processos Erlang é de cerca de 0,8µs. Para C #, são necessários cerca de 50 µs por mensagem, até o número máximo de processos (que eram cerca de 1800 processos). O Java foi ainda pior: para até 100 processos, foram necessários cerca de 50µs por mensagem; depois, aumentou rapidamente para 10ms por mensagem, quando havia cerca de 1000 processos Java.
Meus pensamentos
Não entendo tecnicamente completamente por que os processos Erlang são muito mais eficientes na geração de novos processos e têm pegadas de memória muito menores por processo. O SO e a Erlang VM precisam fazer agendamento, alternar o contexto e acompanhar os valores nos registros e assim por diante ...
Simplesmente por que os threads do SO não são implementados da mesma maneira que os processos em Erlang? Eles têm que apoiar algo mais? E por que eles precisam de uma maior pegada de memória? E por que eles têm reprodução e comunicação mais lentas?
Tecnicamente, por que os processos em Erlang são mais eficientes do que os threads do SO quando se trata de geração e comunicação? E por que os threads no sistema operacional não podem ser implementados e gerenciados da mesma maneira eficiente? E por que os threads do sistema operacional têm uma maior área de armazenamento de memória, além de geração e comunicação mais lentas?
erl +P 1000100 +hms 100
e digite{_, PIDs} = timer:tc(lists,map,[fun(_)->spawn(fun()->receive stop -> ok end end) end, lists:seq(1,1000000)]).
e espere cerca de três minutos para obter o resultado. Isso é tão simples. São necessários 140us por processo e 1 GB de RAM inteira no meu laptop. Mas é diretamente do shell, deve ser melhor do código compilado.Respostas:
Existem vários fatores contribuintes:
fonte
Depois de mais algumas pesquisas, encontrei uma apresentação de Joe Armstrong.
De Erlang - software para um mundo simultâneo (apresentação) (aos 13 min):
Eu acho que responde, se não todas, pelo menos algumas das minhas perguntas
fonte
Eu implementei corotinas no assembler e medi o desempenho.
A alternância entre corotinas, também conhecidas como processos Erlang, leva cerca de 16 instruções e 20 nanossegundos em um processador moderno. Além disso, você costuma conhecer o processo para o qual está mudando (exemplo: um processo que recebe uma mensagem em sua fila pode ser implementado como transferência direta do processo de chamada para o processo de recebimento) para que o planejador não entre em ação, tornando é uma operação O (1).
Para alternar os threads do sistema operacional, leva de 500 a 1000 nanossegundos, porque você está ligando para o kernel. O planejador de encadeamentos do SO pode ser executado no tempo O (log (n)) ou O (log (log (n))), que começará a ser perceptível se você tiver dezenas de milhares ou até milhões de encadeamentos.
Portanto, os processos Erlang são mais rápidos e escalam melhor porque a operação fundamental da troca é mais rápida e o agendador é executado com menos frequência.
fonte
Os processos Erlang correspondem (aproximadamente) a linhas verdes em outros idiomas; não há separação imposta pelo sistema operacional entre os processos. (Pode haver uma separação imposta pelo idioma, mas essa é uma proteção menor, apesar de Erlang fazer um trabalho melhor do que a maioria.) Por serem muito mais leves, podem ser usados com muito mais intensidade.
Os threads do sistema operacional, por outro lado, podem ser simplesmente agendados em diferentes núcleos da CPU e (principalmente) são capazes de oferecer suporte ao processamento independente da CPU. Os processos do SO são como threads do SO, mas com uma separação imposta pelo SO muito mais forte. O preço desses recursos é que os threads do sistema operacional e (ainda mais) os processos são mais caros.
Outra maneira de entender a diferença é essa. Supondo que você fosse escrever uma implementação do Erlang no topo da JVM (não uma sugestão particularmente louca), faria com que cada processo do Erlang fosse um objeto com algum estado. Você teria um conjunto de instâncias do Thread (normalmente dimensionadas de acordo com o número de núcleos no sistema host; esse é um parâmetro ajustável nos tempos de execução reais do Erlang, entre outros), que executa os processos do Erlang. Por sua vez, isso distribuirá o trabalho a ser realizado pelos recursos reais do sistema disponíveis. É uma maneira bem legal de fazer as coisas, mas depende totalmenteno fato de que cada processo Erlang individual não faz muito. Tudo bem, é claro; Erlang está estruturado para não exigir que esses processos individuais sejam pesados, pois é o conjunto geral deles que executa o programa.
De muitas maneiras, o problema real é o da terminologia. As coisas que Erlang chama de processos (e que correspondem fortemente ao mesmo conceito no CSP, CCS e, particularmente, no cálculo π) simplesmente não são as mesmas que as linguagens com herança C (incluindo C ++, Java, C # e muitos outros) chamam um processo ou um encadeamento. Existem algumas semelhanças (todas envolvem alguma noção de execução simultânea), mas definitivamente não há equivalência. Portanto, tenha cuidado quando alguém lhe disser "processo"; eles podem entender que isso significa algo totalmente diferente ...
fonte
Acho que o Jonas queria alguns números na comparação de threads do sistema operacional com os processos Erlang. O autor da programação de Erlang, Joe Armstrong, testou há um tempo a escalabilidade da geração dos processos Erlang nos threads do sistema operacional. Ele escreveu um servidor Web simples em Erlang e o testou contra o Apache com vários threads (já que o Apache usa threads do SO). Há um site antigo com dados que remontam a 1998. Eu consegui encontrar esse site exatamente uma vez. Portanto, não posso fornecer um link. Mas a informação está lá fora. O ponto principal do estudo mostrou que o Apache atingiu o máximo de menos de 8 mil processos, enquanto o servidor Erlang escrito manualmente lidava com 10 mil + processos.
fonte
Como o intérprete Erlang precisa se preocupar apenas com ele, o sistema operacional tem muitas outras coisas com que se preocupar.
fonte
um dos motivos é que o processo erlang é criado não no sistema operacional, mas na evm (máquina virtual erlang), portanto, o custo é menor.
fonte