Je crois que la communauté Erlang n'est pas envieuse de Node.js car elle fait des E / S non bloquantes en natif et a des moyens de faire évoluer facilement les déploiements sur plus d'un processeur (quelque chose qui n'est même pas intégré dans Node.js). Plus de détails sur http://journal.dedasys.com/2010/04/29/erlang-vs-node-js et Node.js ou Erlang
Et Haskell? Haskell peut-il fournir certains des avantages de Node.js, à savoir une solution propre pour éviter de bloquer les E / S sans avoir recours à la programmation multi-thread?
Il y a beaucoup de choses qui sont attrayantes avec Node.js
- Événements: aucune manipulation de thread, le programmeur ne fournit que des rappels (comme dans le framework Snap)
- Les rappels sont garantis pour être exécutés dans un seul thread: aucune condition de concurrence possible.
- API simple et conviviale pour UNIX. Bonus: Excellent support HTTP. DNS également disponible.
- Chaque E / S est par défaut asynchrone. Cela permet d'éviter plus facilement les verrous. Cependant, trop de traitement CPU dans un rappel aura un impact sur les autres connexions (dans ce cas, la tâche doit être divisée en sous-tâches plus petites et reprogrammée).
- Même langage côté client et côté serveur. (Je ne vois cependant pas trop de valeur dans celui-ci. JQuery et Node.js partagent le modèle de programmation d'événements, mais le reste est très différent. Je ne vois tout simplement pas comment le partage de code entre côté serveur et côté client pourrait être utile dans la pratique.)
- Tout cela emballé dans un seul produit.
Réponses:
Ok, donc après avoir regardé un peu la présentation de node.js vers laquelle @gawi m'a pointé, je peux en dire un peu plus sur la façon dont Haskell se compare à node.js. Dans la présentation, Ryan décrit certains des avantages de Green Threads, mais continue en disant qu'il ne trouve pas que le manque d'abstraction de thread soit un inconvénient. Je ne suis pas d'accord avec sa position, en particulier dans le contexte de Haskell: je pense que les abstractions que les threads fournissent sont essentielles pour rendre le code du serveur plus facile à obtenir et plus robuste. En particulier:
l'utilisation d'un thread par connexion vous permet d'écrire du code qui exprime la communication avec un seul client, plutôt que d'écrire du code qui traite avec tous les clients en même temps. Pensez-y comme ceci: un serveur qui gère plusieurs clients avec des threads ressemble presque à celui qui gère un seul client; la principale différence est qu'il y a
fork
quelque part dans le premier. Si le protocole que vous implémentez est complexe, la gestion simultanée de la machine d'état pour plusieurs clients devient assez délicate, tandis que les threads vous permettent de simplement écrire la communication avec un seul client. Le code est plus facile à obtenir correctement, et plus facile à comprendre et à maintenir.les rappels sur un seul thread OS sont du multitâche coopératif, par opposition au multitâche préemptif, ce que vous obtenez avec les threads. Le principal inconvénient du multitâche coopératif est que le programmeur est responsable de s'assurer qu'il n'y a pas de famine. Il perd sa modularité: faites une erreur en un seul endroit, et il peut foutre tout le système. C'est vraiment quelque chose dont vous ne voulez pas vous soucier, et la préemption est la solution simple. De plus, la communication entre les rappels n'est pas possible (cela entraînerait un blocage).
la concurrence n'est pas difficile dans Haskell, car la plupart du code est pur et donc thread-safe par construction. Il existe de simples primitives de communication. Il est beaucoup plus difficile de se tirer une balle dans le pied avec la concurrence dans Haskell que dans une langue avec des effets secondaires illimités.
la source
Oui, en fait, les événements et les threads sont unifiés dans Haskell.
Les threads sont en fait implémentés en termes d'événements et s'exécutent sur plusieurs cœurs, avec une migration transparente des threads, avec des performances documentées et des applications.
Par exemple pour
Collections simultanées nbody sur 32 cœurs
Dans Haskell, vous avez à la fois des événements et des threads, et comme ce sont tous les événements sous le capot.
Lisez le document décrivant la mise en œuvre.
la source
Tout d'abord, je ne pense pas que node.js fasse la bonne chose en exposant tous ces rappels. Vous finissez par écrire votre programme en CPS (style de passage continu) et je pense que ce devrait être le travail du compilateur de faire cette transformation.
Donc, avec cela à l'esprit, vous pouvez écrire en utilisant un style asynchrone si vous le souhaitez, mais en le faisant, vous manqueriez d'écrire dans un style synchrone efficace, avec un thread par demande. Haskell est ridiculement efficace en code synchrone, surtout par rapport à d'autres langages. Ce sont tous les événements en dessous.
Vous pouvez toujours avoir une condition de concurrence dans node.js, mais c'est plus difficile.
Chaque demande est dans son propre fil. Lorsque vous écrivez du code qui doit communiquer avec d'autres threads, il est très simple de le rendre threadsafe grâce aux primitives de concurrence de haskell.
Jetez un œil au piratage et voyez par vous-même.
Vous n'avez pas de tels problèmes, ghc distribuera votre travail entre les vrais threads du système d'exploitation.
Haskell ne peut probablement pas gagner ici ... non? Détrompez-vous, http://www.haskell.org/haskellwiki/Haskell_in_web_browser .
Téléchargez ghc, lancez la cabale. Il y a un forfait pour chaque besoin.
la source
Personnellement, je considère Node.js et la programmation avec des rappels comme un niveau inutilement bas et un peu contre nature. Pourquoi programmer avec des rappels alors qu'un bon runtime tel que celui trouvé dans GHC peut gérer les rappels pour vous et le faire assez efficacement?
Dans l'intervalle, le temps d'exécution du GHC s'est considérablement amélioré: il comporte désormais un "nouveau nouveau gestionnaire d'E / S" appelé MIO, où "M" signifie multicœur, je crois. Il s'appuie sur les fondations du gestionnaire d'E / S existant et son objectif principal est de surmonter la cause de la dégradation des performances de 4+ cœurs. Les performances fournies dans cet article sont assez impressionnantes. Voyez-vous:
Et:
Mio a intégré la version GHC 7.8.1. Personnellement, je vois cela comme une avancée majeure dans la performance de Haskell. Il serait très intéressant de comparer les performances des applications Web existantes compilées par la version précédente de GHC et 7.8.1.
la source
Les événements à mon humble avis sont bons, mais la programmation au moyen de rappels ne l'est pas.
La plupart des problèmes qui rendent le codage et le débogage spéciaux des applications Web proviennent de ce qui les rend évolutifs et flexibles. Le plus important, la nature sans état de HTTP. Cela améliore la navigabilité, mais cela impose une inversion de contrôle où l'élément IO (le serveur Web dans ce cas) appelle différents gestionnaires dans le code d'application. Ce modèle d'événement - ou modèle de rappel, plus précisément - est un cauchemar, car les rappels ne partagent pas des portées variables et une vue intuitive de la navigation est perdue. Il est très difficile d'empêcher tous les changements d'état possibles lorsque l'utilisateur navigue d'avant en arrière, entre autres problèmes.
On peut dire que les problèmes sont similaires à la programmation GUI où le modèle d'événement fonctionne bien, mais les GUI n'ont pas de navigation et pas de bouton de retour. Cela multiplie les transitions d'états possibles dans les applications Web. Le résultat de la tentative de résoudre ces problèmes sont des cadres lourds avec des configurations compliquées, de nombreux identifiants magiques omniprésents sans remettre en cause la racine du problème: le modèle de rappel et son manque inhérent de partage de portées variables, et pas de séquencement, de sorte que la séquence doit être construit en reliant les identifiants.
Il existe des cadres basés séquentiels comme ocsigen (ocaml) bord de mer (smalltalk) WASH (abandonné, Haskell) et mflow (Haskell) qui résolvent le problème de la gestion des états tout en maintenant la navigabilité et la plénitude REST. dans ces cadres, le programmeur peut exprimer la navigation comme une séquence impérative où le programme envoie des pages et attend les réponses dans un seul thread, les variables sont dans la portée et le bouton de retour fonctionne automatiquement. Cela produit par nature un code plus court, plus sûr et plus lisible où la navigation est clairement visible pour le programmeur. (juste avertissement: je suis le développeur de mflow)
la source
La question est assez ridicule car 1) Haskell a déjà résolu ce problème d'une bien meilleure manière et 2) à peu près de la même manière qu'Erlang. Voici la référence par rapport au nœud: http://www.yesodweb.com/blog/2011/03/preliminary-warp-cross-language-benchmarks
Donnez à Haskell 4 cœurs et il peut faire 100 000 requêtes (simples) par seconde dans une seule application. Le nœud ne peut pas en faire autant et ne peut pas faire évoluer une seule application sur plusieurs cœurs. Et vous n'avez rien à faire pour récolter cela car le runtime Haskell n'est pas bloquant. Le seul autre langage (relativement commun) qui intègre des E / S non bloquantes dans l'exécution est Erlang.
la source
pm2 -i max path/to/app.js
évoluera automatiquement vers le nombre optimal d'instances en fonction des cœurs disponibles. De plus, Node est également non bloquant par défaut.Tout comme nodejs a chuté libev le Web Framework snap Haskell a chuté libev aussi.
la source