Pourquoi est-Erlang plus lent que Java sur toutes ces petites maths repères?
Tout en tenant compte des solutions de rechange pour Java pour un distribuée/simultanée/basculement/évolutive backend de l'environnement, j'ai découvert Erlang. J'ai passé un peu de temps sur les livres et les articles où presque tous d'entre eux (même Java accro gars) dit que Erlang est un meilleur choix dans de tels environnements, comme beaucoup de choses utiles sont hors de la boîte est moins sujette aux erreurs manière.
J'étais sûr que Erlang est plus rapide dans la plupart des cas, principalement en raison d'un autre de collecte des ordures de la stratégie (par processus), l'absence d'un état partagé (b/w threads et de processus) et plus compact types de données. Mais j'ai été très surpris quand j'ai découvert comparaisons des Erlang vs Java math échantillons où Erlang est plus lent de plusieurs ordres, par exemple à partir x10 x100.
Même des tâches simultanées, à la fois sur plusieurs cœurs et une seule.
Quelles sont les raisons? Ces réponses sont venues à l'esprit:
- L'utilisation de Java primitives (=> pas de tas/gc) sur la plupart des tâches
- Même nombre de threads dans le code Java et le processus Erlang alors l'acteur modèle n'a pas d'avantage ici
- Ou simplement le fait que Java est statiquement typé, tout en Erlang n'est pas
- Quelque chose d'autre?
Si c'est parce que ces sont très particuliers de mathématiques des algorithmes, quelqu'un peut-il montrer plus réel/la pratique de tests de performance?
Mise à JOUR: j'ai les réponses indiquant que Erlang n'est pas le bon outil pour chaque "fast Java cas", mais la chose qui est claire pour moi - ce qui est la raison principale de ces Erlang inefficacité ici: typage dynamique, GC ou pauvres indigènes de la compilation?
- Très bonne question, je serais ravi de voir les réponses moi-même.
- Java compile mathématiques assez efficacement du code machine natif et est souvent presque aussi rapide que du C++ 😉 je soupçonne erlang n'est pas. Vous pouvez essayer l'option de ligne de commande
-nojit
pour voir si cela ralentit Java à peu près la même. - Java compile mathématiques assez efficacement du code machine natif je suis sûr que vous savez il n'y a pas de byte code pour les mathématiques )) l'efficacité est ici détriment de primitives/pas d'objets, etc, si je mettre en œuvre le même calcul avec des Objets/Wrappers - les résultats seront très pire
- btw, pourquoi ne pas erlang HiPE natif de la compilation d'arriver ou pourquoi est-il 10 fois plus lent?
- Plaine Erlang par rapport à HiPE shootout.alioth.debian.org/u64q/...
- comparer les mathématiques sur des nombres à travers de 10 000 threads et de voir laquelle est la plus rapide? puis le faire distribués, de revenir et de nous dire pourquoi vous pensez que cette réponse est constructive alors ( indice de référence des questions sont rarement constructif )
- vrai, mais si j'ai un code tel dirstributed mathématiques avec les threads java num = core num (le tout par les exécuteurs testamentaires) +pas de synchronisation +envoyer que des primitives via le réseau, etc - Je doute que java sera plus lent, il peut être plus verbeux, susceptible de causer des erreurs, moins évolutive, etc, mais encore plus rapide, vous ne pensez pas?
- Dans les deux cas, je pense que vous serait toujours l'écriture et le débogage de code, des jours peut-être semaines après le programmeur erlang avait fini leur code, et déplacé sur un autre contrat 🙂 Mon point est que vous avez manqué, retirez l'artificiel "petits repères" et de les faire monde réel des cas et montrer comment la non-constructive de cet indice de référence est.
- Roberson -- me Semble que
yetanothercoderu
est à la recherche d'une explication technique de ce qu'est exactement la JVM et HiPE faire différemment dans ces cas, qui donne lieu à l'observé de différence de performances. afaict nos réponses n'ont pas été constructif parce que nous ne savons tout simplement pas. - C'est la façon dont je l'ai lu aussi. "Il n'est pas construit pour elle" n'est pas vraiment une réponse, est-il.
- pourquoi ne pas mon Ferrari courriers pizzas aussi efficacement que mon Hyundai? Je veux dire vraiment pourquoi ma Ferrari brûler beaucoup plus de gaz et le coût beaucoup plus à tenir juste pour livrer quelques pizzas chaque nuit? Et ne me dites pas "il n'a pas été conçu pour le faire"!
Vous devez vous connecter pour publier un commentaire.
Erlang n'a pas été construit pour les mathématiques. Il a été construit avec de la communication, le traitement parallèle et l'évolutivité à l'esprit, afin de le tester pour des tâches mathématiques est un peu comme le test si votre marteau-piqueur vous donne massage rafraîchissant de l'expérience.
Cela dit, nous allons offtop un peu:
Si vous voulez Erlang-style de programmation dans la JVM, jetez un oeil à Scala Acteurs ou Akka cadre ou Vert.x.
Repères ne sont jamais bonnes pour dire autre chose que ce qu'ils sont vraiment tester. Si vous sentez qu'un critère est seulement de tester primitives et un classique de modèle de thread, c'est ce que vous obtenez des connaissances sur. Vous pouvez maintenant avec une certaine confiance dire que Java est plus rapide que Erlang sur les mathématiques sur des primitives ainsi que le classique modèle de thread pour ces types de problèmes. Vous ne savez rien à propos de la performance, avec un grand nombre de threads ou pour impliquer davantage de problèmes parce que l'indice de référence n'a pas le tester.
Si vous faites les types de maths que l'indice de référence testé, aller à Java, car il est de toute évidence le bon outil pour ce travail. Si vous voulez faire quelque chose de fortement évolutif avec peu ou pas de l'état partagé, trouver un point de référence pour que ou à moins de ré-évaluer Erlang.
Si vous avez vraiment besoin de faire de lourds mathématiques en Erlang, pensez à utiliser HiPE (tenir compte de toute façon que ce soit).
Comme l'a fait observer dans d'autres réponses - Erlang est conçu pour résoudre efficacement les problèmes de la vie réelle qui sont peu face à des problèmes de référence.
Mais je tiens à éclairer un aspect - pourriture molle de erlang code (dans certains cas, signifie rapidité de développement), ce qui pourrait facilement être conclu, après comparaison des repères implémentations.
Par exemple, k-nucléotides de référence:
Erlang version: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=hipe&id=3
Java version: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=java&id=3
Si vous voulez plus de la vie réelle de repères, je vous suggère de vous La Comparaison De C++ Et Erlang Pour Motorola Télécoms Logiciel
J'ai pris intérêt à ce que certains de ces indicateurs sont un ajustement parfait pour erlang, telles que le séquençage des gènes. Donc sur http://benchmarksgame.alioth.debian.org/ la première chose que j'ai fait était de regarder à l'inverse de compléter les implémentations en C et en Erlang, ainsi que les essais de détails. J'ai trouvé que le test est biaisé car il ne négligez pas le temps qu'il faut erlang pour démarrer la VM /w les planificateurs, nativement compilée en C est beaucoup plus rapide. La façon dont ces critères de mesure est en gros:
time erl -noshell -s revcomp5 main < revcomp-input.txt
Maintenant la référence dit que Java a 1,4 secondes et erlang /w HiPE a eu 11. L'exécution de l' (Mono-thread) Erlang code m'a pris 0,15 secondes, et si vous le rabais le temps qu'il a fallu pour démarrer la machine virtuelle, la charge de travail a pris seulement 3 000 microsecondes (0.003 secondes).
Donc je n'ai aucune idée de comment cela est comparable, si sa fait 100 fois, puis il ne fait aucun sens que le coût de démarrage de l'erlang de la machine virtuelle sera x100. Si l'entrée est beaucoup plus long que donné, il serait logique, mais je ne vois pas de détails sur la page web de ce. Pour faire les repères plus juste pour les langues, le code (Erlang/Java) d'envoyer un signal Unix pour le python (qui est en train de faire le benchmarking) qu'il a frappé la fonction de démarrage.
Maintenant de référence de côté, l'erlang VM essentiellement juste exécute le code machine, à la fin, ainsi que la machine virtuelle Java. Il n'est donc pas une opération mathématique prendrait plus de temps en Erlang que dans Java.
Ce Erlang est mauvaise est une donnée qui doit muter souvent. Comme enchaînés, bloc de cypher. Dire que vous avez l'chars "0123456789", désormais votre de chiffrement xors les 2 premiers caractères par 7, puis xors les deux caractères par le résultat des deux premiers ajouté, puis xors la précédente de 2 caractères, par les résultats de l'actuelle 2 soustrait, puis xors les 4 caractères.. etc
Car les objets en Erlang sont immuables cela signifie que l'ensemble du char tableau doit être copiés à chaque fois que vous transformer. C'est pourquoi erlang a un support pour les choses que l'on appelle NIF qui est le code C, vous pouvez appeler pour résoudre ce problème exact. En fait, tout le chiffrement (ssl,aes,blowfish..) et de compression (zlib,..) livrés avec Erlang sont implémentés en C, il y a aussi près de 0 coût associé à l'appel de C à partir d'Erlang.
Donc à l'aide d'Erlang, vous obtenez le meilleur des deux mondes, vous obtenez la vitesse de C avec le parallélisme d'Erlang.
Si je devais mettre en œuvre l'inverse en complément de la façon la plus RAPIDE possible, je voudrais écrire la mutation de code à l'aide de C, mais le code en parallèle à l'aide de Erlang. En supposant infini d'entrée, j'aurais Erlang split sur le >
<<Line/binary, ">", Rest/binary>> = read_stream
Expédition le bloc à la première disponible via le planificateur de tournoi à la ronde, composé de l'infini EC2 privé en réseau caché nœuds, ajoutés en temps réel pour le cluster à chaque milliseconde.
Ces nœuds, puis d'appeler à C via NIF pour le traitement (C était le plus rapide de mise en œuvre pour inverser-compliment sur alioth site web), puis envoyer la sortie vers le nœud maître, pour les envoyer à la inputer.
Pour le mettre en oeuvre en Erlang j'aurais à écrire du code comme si j'écrivais un seul programme multi-threadé, ça me prendra moins d'une journée pour créer ce code.
Mettre en Java, je dois écrire le single threaded code, je dois prendre l'impact sur les performances de l'appel de Géré non géré (comme nous le seront à l'aide de la C mise en œuvre de la partie la plus rébarbative évidemment), puis le réécrire à l'appui de 64 cœurs. Puis le réécrire en charge plusieurs PROCESSEURS. Puis le réécrire à nouveau pour prendre en charge le clustering. Puis le réécrire à nouveau pour résoudre des problèmes de mémoire.
Et qui est d'Erlang en un mot.
L'Erlang solution utilise ETS, Erlang Stockage à long Terme, qui est comme une base de données en mémoire d'exécution dans un processus séparé. Conséquent, à être dans un processus distinct, tous les messages vers et à partir de ce processus de faut sérialiser/désérialiser. Ce serait compte pour beaucoup, de la lenteur, je pense. Par exemple, si vous regardez les "regex de l'adn" de référence, Erlang n'est que légèrement plus lent que le Java il y a, et il n'utilise pas les ETS.
Le fait que erlang a pour allouer de la mémoire pour chaque valeur, tandis qu'en java, vous aurez généralement la réutilisation des variables si vous voulez qu'il soit rapide, signifie qu'il va toujours être plus rapide pour la 'boucle' banc de marques.
Il serait intéressant de comparer une version de java à l'aide de l'indicateur du client et de la boîte de primitives et de la comparer à erlang.
Je crois que l'aide hipe est injuste car il n'est pas un projet actif. Je serais intéressé de savoir si essentielles à la mission de logiciel est en cours d'exécution sur ce.
Je ne sais rien à propos de Erlang, mais cela semble être un comparer des pommes avec des oranges approche de toute façon. Vous devez être conscient qu'un effort considérable a été consacré depuis plus d'une décennie pour améliorer la java performance, au point où il est aujourd'hui.
Il n'est pas surprenant (pour moi) qu'un langage de mise en œuvre réalisé par des bénévoles ou d'une petite entreprise ne peut pas outmatch cet effort.