Mélange Erlang et Haskell
Si vous avez acheté dans le paradigme de la programmation fonctionnelle, les chances sont que vous aimez à la fois Erlang et Haskell. Les deux ont des cœurs purement fonctionnels et d'autres qualités telles que des threads légers qui les rendent bien adaptés à un monde multicœur. Mais il existe des différences aussi.
Erlang est un langage commercialement éprouvé tolérant aux pannes avec un modèle de distribution mature. Il a une caractéristique apparemment unique dans sa capacité à mettre à niveau sa version à l'exécution via le chargement de code à chaud. (Cool!)
Haskell, d'autre part, a le système de type le plus sophistiqué de toute langue dominante. (Où je définis "mainstream" comme n'importe quelle langue qui a un livre o'Reilly publié, donc Haskell compte.) Sa performance simple filetée droite semble supérieure à celle D'Erlang et ses fils légers semblent encore plus légers.
J'essaie de mettre en place une plate-forme de développement pour le reste de ma vie de codage et je me demandais s'il était possible de mélanger Erlang et Haskell pour atteindre un meilleur de la plate-forme de race. Cette question a deux parties:
- je voudrais utiliser Erlang comme une sorte de MPI tolérant aux pannes pour coller les instances D'exécution GHC ensemble. Il y aurait un processus Erlang par exécution GHC. Si "l'impossible s'est produit" et que le runtime GHC est mort, alors le processus Erlang le détecterait d'une manière ou d'une autre et mourrait aussi. Les fonctionnalités de chargement et de distribution de code à chaud d'Erlang continueraient à fonctionner. Le runtime GHC peut être configuré pour utiliser juste un noyau, ou tous les noyaux sur la machine locale, ou n'importe quelle combinaison entre les deux. Une fois la bibliothèque Erlang écrite, le reste du code de niveau Erlang doit être purement standard et généré automatiquement par application. (Peut - être par un DSL Haskell par exemple.) Comment atteindre au moins certaines de ces choses?
- J'aimerais Qu'Erlang et Haskell puissent partager le même collecteur de garabage. (Ceci est une idée beaucoup plus loin que 1.) Langues qui s'exécutent sur la JVM et le CLR atteindre une plus grande masse en partageant un temps d'exécution. Je comprends qu'il existe des limitations techniques pour exécuter Erlang (chargement de code à chaud) et Haskell (polymorphisme de type supérieur) sur la JVM ou le CLR. Mais qu'en est-il du dégroupage juste le garbage collector? (Sorte de début d'un runtime pour les langages fonctionnels.) L'Allocation devrait évidemment encore être très rapide, alors peut-être que ce bit doit être lié statiquement. Et il devrait y avoir quelques mechansim pour distinguer le mutable tas du tas immuable (en incluant l'écriture paresseuse une fois la mémoire) comme GHC en a besoin. Serait-il possible de modifier à la fois HIPE et GHC afin que les éboueurs puissent partager un tas?
Veuillez répondre avec des expériences (positives ou négatives), des idées ou des suggestions. En fait, toute rétroaction (à court d'abus droit!) est la bienvenue.
Mise à Jour
Merci pour les 4 réponses à ce jour-chacune m'a appris au moins une chose utile que je n'ai pas savoir.
En ce qui concerne le reste de la vie de codage chose-je l'ai inclus légèrement la langue dans la joue pour susciter le débat, mais c'est en fait vrai. Il y a un projet que j'ai en tête et sur lequel j'ai l'intention de travailler jusqu'à ma mort, et il a besoin d'une plate-forme stable.
Dans la plate-forme que j'ai proposée ci-dessus, je n'écrirais que Haskell, car L'Erlang standard serait automatiquement généré. Alors combien de temps Haskell va-t-il durer? Eh bien Lisp est toujours avec nous et n'a pas l'air de s'en aller sitôt. Haskell est BSD3 open source et a atteint la masse critique. Si la programmation elle-même est encore là dans 50 ans, je m'attendrais à ce que Haskell, ou une évolution continue de Haskell, soit toujours là.
Mise à jour 2 en réponse au message de rvirding
Convenu-implémenter une machine virtuelle universelle complète "Erskell/Haslang" n'est peut-être pas absolument impossible, mais ce serait certainement très difficile. Partage juste les ordures le niveau du collecteur comme quelque chose comme une machine virtuelle, tout en restant difficile , me semble un ordre de grandeur moins difficile. Dans le modèle de collecte des ordures, les langages fonctionnels doivent avoir beaucoup en commun - l'absence de données immuables (y compris thunks) et l'exigence d'une allocation très rapide. Donc, le fait que commonality soit étroitement associé à des machines virtuelles monolithiques semble un peu étrange.
Les machines virtuelles aident à atteindre la masse critique. Il suffit de regarder comment les langages fonctionnels "lite" comme F# et Scala ont décollé. Scala peut ne pas avoir la tolérance aux pannes absolue D'Erlang, mais il offre une voie d'évacuation pour les très nombreuses personnes qui sont liées à la JVM.
Tout en ayant un seul tas fait message passant très vite il introduit un certain nombre d'autres problèmes, principalement Que faire GC devient plus difficile, car il doit être interactif et globalement non interruptive de sorte que vous impossible d'utiliser les mêmes algorithmes plus simples comme le tas par processus modèle.
Absolument, cela a un sens parfait pour moi. Les personnes très intelligentes de L'équipe de développement de GHC semblent essayer de résoudre une partie du problème avec un GC parallèle "stop the world".
Http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel-gc/par-gc-ismm08.pdf
(évidemment "arrêter le monde" ne volerait pas pour le général Erlang étant donné son cas d'utilisation principal.) Mais même dans les cas d'utilisation où "arrêter le monde" est OK, leurs accélérations le font semble pas être universelle. Donc, je suis d'accord avec vous, il est peu probable qu'il y ait un GC universellement meilleur, ce qui est la raison pour laquelle j'ai spécifié dans la partie 1. de ma question que
Le runtime GHC peut être configuré pour utilisez un seul noyau, ou tous les noyaux sur le machine locale, ou toute combinaison dans entre.
De cette façon, pour un cas d'utilisation donné, je pourrais, après benchmarking, choisir D'aller dans la voie Erlang, et exécuter un runtime GHC (avec un GC singlethreaded) plus un Erlang traiter par cœur et laisser Erlang copier la mémoire entre les cœurs pour une bonne localité.
Alternativement, sur une machine à double processeur avec 4 cœurs par processeur avec une bonne bande passante mémoire sur le processeur, l'analyse comparative pourrait suggérer que j'exécute un runtime GHC (avec un GC parallèle) plus un processus Erlang par processeur.
Dans les deux cas, si Erlang et GHC pouvaient partager un tas, le partage serait probablement lié à un seul thread OS s'exécutant sur un seul cœur. (Je suis sortir de ma ici, c'est pourquoi j'ai posé la question.)
J'ai aussi un autre agenda-benchmarking des langages fonctionnels indépendamment du GC. Souvent, je lis des résultats de benchmarks de OCaml V GHC V Erlang v... et je me demande combien les résultats sont confondus par les différents GCs. Et si le choix du GC pouvait être orthogonal au choix du langage fonctionnel? Combien coûte GC de toute façon? Voir ce blog Devil advocates
Http://john.freml.in/garbage-collection-harmful
Par Mon Ami Lisp John Fremlin, qu'il a, avec charme, donné son titre de poste "la collecte automatisée des ordures est des ordures". Lorsque John prétend que GC est lent et n'a pas vraiment accéléré autant, j'aimerais pouvoir contrer avec quelques chiffres.
6 réponses
Beaucoup de gens de Haskell et D'Erlang sont intéressés par le modèle où Erlang supervise la distribution, tandis que Haskell exécute les nœuds de mémoire partagée en parallèle en faisant tout le nombre/logique.
Un début vers ceci est la bibliothèque haskell-erlang: http://hackage.haskell.org/package/erlang
Et nous avons les mêmes efforts en Ruby terre, par Orgueil: http://github.com/mwotton/Hubris/tree/master
La question est maintenant de trouver quelqu'un pour réellement poussez à travers L'interop Erlang / Haskell pour découvrir les problèmes difficiles.
Vous allez avoir un moment intéressant de mélange GC entre Haskell et Erlang. Erlang utilise un tas par processus et copie les données entre les processus - comme Haskell n'a même pas de concept de processus, Je ne sais pas comment vous mapperiez ce GC "universel" entre les deux. En outre, pour de meilleures performances, Erlang utilise une variété d'allocateurs, chacun avec des comportements légèrement modifiés qui, je suis sûr, affecteraient le sous-système GC.
Comme avec toutes les choses dans le logiciel, l'abstraction vient à un coût. Dans ce cas, je soupçonne plutôt que vous deviez introduire autant de couches pour obtenir les deux langues sur leur incompatibilité d'impédance que vous finiriez avec une machine virtuelle commune pas très performante (ou utile).
Bottom line -- embrassez la différence! Il y a d'énormes avantages à ne pas tout Exécuter dans le même processus, en particulier du point de vue de la fiabilité. Aussi, je pense qu'il est un peu naïf de s'attendre à ce qu'une langue / VM vous dure pour le reste de votre vie (sauf si vous prévoyez un.) peu de temps ou B.) devenir une sorte de moine de code qui ne fonctionne que sur un seul projet). Le développement de logiciels est tout au sujet de l'agilité mentale et d'être prêt à utiliser les meilleurs outils disponibles pour construire un code rapide et fiable.
Bien que ce soit un sujet assez ancien, si les lecteurs sont toujours intéressés, il vaut la peine de jeter un oeil à Cloud Haskell , qui apporte la concurrence et la distribution de style Erlang à L'écurie GHC.
La prochaine bibliothèque distributed-process-platform prend en charge les constructions OTP-esque telles que gen_servers, les arbres de supervision et diverses autres abstractions "Haskell" empruntées et inspirées par Erlang/OTP.
Vous pouvez utiliser un processus OTP gen_supervisor pour surveiller les instances Haskell que vous générez avec open_port (). Selon la façon dont le "port" est sorti, vous seriez alors en mesure de le redémarrer ou de décider qu'il s'est arrêté exprès et de laisser mourir le processus Erlang correspondant.
Fugheddaboudit. Même ces machines virtuelles indépendantes de la langue dont vous parlez ont parfois des problèmes avec les données transmises entre les langues. Vous devriez simplement sérialiser les données entre les deux en quelque sorte: base de données, XML-RPC, quelque chose comme ça.
En passant, l'idée d'une plate-forme unique pour le reste de votre vie est probablement impraticable, aussi. La technologie informatique et la mode changent trop souvent pour s'attendre à ce que vous puissiez continuer à utiliser une seule langue pour toujours. Votre question précise ceci: aucune langue ne fait tout ce que nous pourrions souhaiter, même aujourd'hui.
Comme dizzyd mentionné dans son commentaire Toutes les données des messages ne sont pas copiées, les binaires volumineux existent en dehors des tas de processus et ne sont pas copiés.
Utiliser une structure de mémoire différente pour éviter d'avoir des tas séparés par processus est certainement possible et a été fait dans un certain nombre d'implémentations antérieures. Tout en ayant un seul tas rend le passage de message Très rapide, il introduit un certain nombre d'autres problèmes, principalement Que faire GC devient plus difficile car il doit être interactif et globalement non interruptif, vous ne pouvez donc pas utiliser les mêmes algorithmes plus simples que le modèle de tas par processus.
Tant que nous utilisons des structures de données immuables, il n'y a pas de problème de robustesse et de sécurité. Décider quels modèles de mémoire et de GC utiliser est un gros compromis,et malheureusement il y a le meilleur modèle universellement.
Alors que Haskell et Erlang sont tous deux des langages fonctionnels, ils sont à bien des égards des langages très différents et ont des implémentations très différentes. Il serait difficile de trouver une machine "Erskell" (ou Haslang) qui pourrait gérer efficacement les deux langues. Personnellement, je pense qu'il est beaucoup mieux de les garder séparés et de s'assurer que vous avez une très bonne interface entre eux.
Le CLR prend en charge l'optimisation des appels de queue avec un Opcode tail
explicite (tel qu'utilisé par F#), que la JVM n'a pas (encore) d'équivalent, ce qui limite l'implémentation d'un tel style de langage. L'utilisation de AppDomain
s séparés permet au CLR de changer de code à chaud (voir par exemple Cet article de blog montrant comment cela peut être fait).
Avec Simon Peyton Jones travaillant juste en bas du couloir de Don Syme et de L'équipe F# de Microsoft Research, ce serait une grande déception si nous ne le faisions pas finalement voir un IronHaskell avec une sorte de statut officiel. Un IronErlang serait un projet intéressant - le plus gros travail serait probablement de porter le planificateur Green-threading sans être aussi lourd que le moteur de flux de travail Windows,ou d'avoir à exécuter une machine virtuelle BEAM sur le CLR.