Caractéristiques d'Erlang
De Erlang Programming (2009):
La concurrence Erlang est rapide et évolutive. Ses processus sont légers en ce que la machine virtuelle Erlang ne crée pas de thread de système d'exploitation pour chaque processus créé. Ils sont créés, planifiés et gérés dans la machine virtuelle, indépendamment du système d'exploitation sous-jacent. En conséquence, le temps de création du processus est de l'ordre de la microseconde et indépendant du nombre de processus existants simultanément. Comparez cela avec Java et C #, où pour chaque processus un thread de système d'exploitation sous-jacent est créé: vous obtiendrez des comparaisons très compétitives, avec Erlang surpassant largement les deux langages.
De la programmation orientée concurrence dans Erlang (pdf) (diapositives) (2003):
Nous observons que le temps nécessaire pour créer un processus Erlang est constant de 1µs jusqu'à 2500 processus; ensuite, il augmente jusqu'à environ 3µs pour jusqu'à 30 000 processus. Les performances de Java et C # sont indiquées en haut de la figure. Pour un petit nombre de processus, il faut environ 300 µs pour créer un processus. Créer plus de deux mille processus est impossible.
Nous voyons que pour jusqu'à 30 000 processus, le temps d'envoi d'un message entre deux processus Erlang est d'environ 0,8 µs. Pour C #, cela prend environ 50µs par message, jusqu'au nombre maximum de processus (qui était d'environ 1800 processus). Java était encore pire, pour jusqu'à 100 processus, il fallait environ 50 µs par message, puis il augmentait rapidement à 10 ms par message alors qu'il y avait environ 1000 processus Java.
Mes pensées
Je ne comprends pas parfaitement pourquoi les processus Erlang sont tellement plus efficaces pour générer de nouveaux processus et ont une empreinte mémoire beaucoup plus petite par processus. Le système d'exploitation et la machine virtuelle Erlang doivent faire la planification, les changements de contexte et garder une trace des valeurs dans les registres, etc.
Pourquoi les threads du système d'exploitation ne sont-ils pas implémentés de la même manière que les processus d'Erlang? Doivent-ils soutenir quelque chose de plus? Et pourquoi ont-ils besoin d'une plus grande empreinte mémoire? Et pourquoi ont-ils une reproduction et une communication plus lentes?
Techniquement, pourquoi les processus d'Erlang sont-ils plus efficaces que les threads du système d'exploitation en ce qui concerne le frai et la communication? Et pourquoi les threads du système d'exploitation ne peuvent-ils pas être implémentés et gérés de la même manière efficace? Et pourquoi les threads du système d'exploitation ont-ils une plus grande empreinte mémoire, ainsi qu'une génération et une communication plus lentes?
erl +P 1000100 +hms 100
et tapez ensuite{_, PIDs} = timer:tc(lists,map,[fun(_)->spawn(fun()->receive stop -> ok end end) end, lists:seq(1,1000000)]).
et attendez environ trois minutes pour obtenir le résultat. C'est si simple. Il faut 140us par processus et 1 Go de RAM entière sur mon ordinateur portable. Mais c'est directement sous forme de shell, ça devrait être mieux à partir du code compilé.Réponses:
Il existe plusieurs facteurs contributifs:
la source
Après quelques recherches supplémentaires, j'ai trouvé une présentation de Joe Armstrong.
Depuis Erlang - logiciel pour un monde simultané (présentation) (à 13 min):
Je pense qu'il répond sinon à toutes, au moins à quelques-unes de mes questions
la source
J'ai implémenté des coroutines dans l'assembleur et mesuré les performances.
La commutation entre les coroutines, alias les processus Erlang, prend environ 16 instructions et 20 nanosecondes sur un processeur moderne. En outre, vous connaissez souvent le processus vers lequel vous basculez (exemple: un processus recevant un message dans sa file d'attente peut être implémenté comme un transfert direct du processus appelant au processus de réception) afin que le planificateur n'entre pas en jeu, ce qui c'est une opération O (1).
Pour changer de thread de système d'exploitation, cela prend environ 500 à 1000 nanosecondes, car vous appelez le noyau. Le planificateur de threads du système d'exploitation peut s'exécuter dans le temps O (log (n)) ou O (log (log (n))), ce qui commencera à être perceptible si vous avez des dizaines de milliers, voire des millions de threads.
Par conséquent, les processus Erlang sont plus rapides et mieux évolutifs car à la fois l'opération fondamentale de commutation est plus rapide et le planificateur s'exécute moins souvent.
la source
Les processus Erlang correspondent (approximativement) à des fils verts dans d'autres langues; il n'y a pas de séparation imposée par le système d'exploitation entre les processus. (Il peut bien y avoir une séparation imposée par la langue, mais c'est une protection moindre malgré qu'Erlang fasse un meilleur travail que la plupart des autres.) Parce qu'ils sont beaucoup plus légers, ils peuvent être utilisés beaucoup plus largement.
Les threads du système d'exploitation, d'autre part, peuvent être simplement planifiés sur différents cœurs de processeur et sont (principalement) capables de prendre en charge un traitement indépendant lié au processeur. Les processus du système d'exploitation sont comme les threads du système d'exploitation, mais avec une séparation renforcée du système d'exploitation. Le prix de ces fonctionnalités est que les threads du système d'exploitation et (encore plus) les processus sont plus chers.
Une autre façon de comprendre la différence est la suivante. Supposons que vous alliez écrire une implémentation d'Erlang au-dessus de la JVM (ce n'est pas une suggestion particulièrement folle) alors vous feriez de chaque processus Erlang un objet avec un état. Vous auriez alors un pool d'instances de Thread (généralement dimensionnées en fonction du nombre de cœurs dans votre système hôte; c'est un paramètre réglable dans les environnements d'exécution réels d'Erlang BTW) qui exécutent les processus Erlang. À son tour, cela répartira le travail à effectuer sur les ressources système réelles disponibles. C'est une façon assez soignée de faire les choses, mais qui dépend totalementsur le fait que chaque processus Erlang individuel ne fait pas grand-chose. C'est OK bien sûr; Erlang est structuré pour ne pas exiger que ces processus individuels soient lourds puisque c'est l'ensemble d'entre eux qui exécute le programme.
À bien des égards, le vrai problème est un problème de terminologie. Les choses qu'Erlang appelle processus (et qui correspondent fortement au même concept dans CSP, CCS, et en particulier le π-calcul) ne sont tout simplement pas les mêmes que les choses que les langages avec un héritage C (y compris C ++, Java, C #, et beaucoup d'autres) appellent un processus ou un fil. Il y a quelques similitudes (toutes impliquent une certaine notion d'exécution simultanée) mais il n'y a certainement pas d'équivalence. Soyez donc prudent lorsque quelqu'un vous dit «processus»; ils pourraient comprendre que cela signifiait quelque chose de complètement différent…
la source
Je pense que Jonas voulait quelques chiffres sur la comparaison des threads OS aux processus Erlang. L'auteur de Programming Erlang, Joe Armstrong, a testé il y a quelque temps l'évolutivité de la génération des processus Erlang vers les threads du système d'exploitation. Il a écrit un serveur Web simple dans Erlang et l'a testé contre Apache multi-thread (car Apache utilise des threads du système d'exploitation). Il existe un ancien site Web dont les données remontent à 1998. Je n'ai réussi à trouver ce site qu'une seule fois. Je ne peux donc pas fournir de lien. Mais l'information est là-bas. Le point principal de l'étude a montré qu'Apache maximisait un peu moins de processus 8K, tandis que son serveur Erlang écrit à la main traitait les processus 10K +.
la source
Parce que l'interpréteur Erlang n'a qu'à se soucier de lui-même, le système d'exploitation a beaucoup d'autres choses à craindre.
la source
l'une des raisons est que le processus erlang n'est pas créé dans le système d'exploitation, mais dans l'evm (machine virtuelle erlang), de sorte que le coût est moindre.
la source