haskell functional-programming erlang garbage-collection ghc

Mezcla de Erlang y Haskell



functional-programming garbage-collection (6)

  1. Puede usar un proceso gen_supervisor de OTP para monitorear las instancias de Haskell que genere con open_port (). Dependiendo de cómo salió el "puerto", usted podría reiniciarlo o decidir que se detuvo a propósito y dejar que el proceso de Erlang correspondiente también muera.

  2. Fugheddaboudit. Incluso estas máquinas virtuales independientes del idioma de las que usted habla tienen problemas con los datos que se transmiten entre los idiomas a veces. Deberías simplemente serializar datos entre los dos de alguna manera: base de datos, XML-RPC, algo así.

Por cierto, la idea de una plataforma única para el resto de tu vida probablemente también sea poco práctica. La tecnología informática y la moda cambian con demasiada frecuencia como para esperar que pueda seguir usando un solo idioma para siempre. Su propia pregunta lo señala: ningún idioma hace todo lo que podríamos desear, incluso hoy.

Si has aceptado el paradigma de la programación funcional, es probable que te gusten tanto Erlang como Haskell. Ambos tienen núcleos puramente funcionales y otras bondades, como hilos ligeros que los hacen adecuados para un mundo multinúcleo. Pero también hay algunas diferencias.

Erlang es un lenguaje tolerante a errores probado comercialmente con un modelo de distribución maduro. Tiene una característica aparentemente única en su capacidad para actualizar su versión en tiempo de ejecución a través de la carga de código caliente. (¡Muy fresco!)

Haskell, por otro lado, tiene el sistema de tipo más sofisticado de cualquier lenguaje convencional. (Donde defino ''mainstream'' como cualquier lenguaje que tenga un libro O''Reilly publicado, así lo cuenta Haskell). Su rendimiento de un solo hilo en línea se ve superior al de Erlang y sus hilos livianos parecen incluso más ligeros.

Estoy tratando de armar una plataforma de desarrollo para el resto de mi vida de codificación y me preguntaba si era posible mezclar Erlang y Haskell para lograr la mejor plataforma de su clase. Esta pregunta tiene dos partes:

  1. Me gustaría usar Erlang como un tipo de MPI tolerante a errores para unir instancias de tiempo de ejecución de GHC. Habría un proceso de Erlang por tiempo de ejecución de GHC. Si "sucedió lo imposible" y el tiempo de ejecución de GHC murió, entonces el proceso de Erlang lo detectaría de alguna manera y también moriría. Las funciones de carga y distribución del código de Erlang seguirían funcionando. El tiempo de ejecución de GHC podría configurarse para usar solo un núcleo, o todos los núcleos en la máquina local, o cualquier combinación intermedia. Una vez que se escribió la biblioteca de Erlang, el resto del código de nivel de Erlang debe ser puramente repetitivo y generado automáticamente por aplicación. (Tal vez por un Haskell DSL, por ejemplo.) ¿Cómo se logra al menos algunas de estas cosas?
  2. Me gustaría que Erlang y Haskell puedan compartir el mismo coleccionista de garabajes. (Esta es una idea mucho más lejana que 1.) Los lenguajes que se ejecutan en la JVM y la CLR logran una mayor masa al compartir un tiempo de ejecución. Entiendo que hay limitaciones técnicas para ejecutar Erlang (carga de código caliente) y Haskell (polimorfismo de mayor par) en la JVM o la CLR. Pero, ¿qué hay de desagregar solo al recolector de basura? (Algo así como el inicio de un tiempo de ejecución para lenguajes funcionales.) La asignación obviamente todavía tiene que ser muy rápida, así que tal vez ese bit deba estar enlazado estáticamente. Y debería haber algún mecanismo para distinguir el montón mutable del montón inmutable ( incluyendo la memoria de escritura lenta) ya que GHC necesita esto. ¿Sería factible modificar tanto HIPE como GHC para que los recolectores de basura compartan un montón?

Responda con cualquier experiencia (positiva o negativa), ideas o sugerencias. De hecho, cualquier comentario (¡menos el abuso directo!) Es bienvenido.

Actualizar

Gracias por las 4 respuestas hasta la fecha; cada una me enseñó al menos una cosa útil que yo no sabía.

En cuanto al resto de la vida de la codificación , lo incluí ligeramente como una mejilla para provocar el debate, pero en realidad es cierto. Hay un proyecto que tengo en mente en el que tengo la intención de trabajar hasta que muera, y que necesita una plataforma estable.

En la plataforma que he propuesto más arriba, solo escribiría Haskell, ya que el prototipo Erlang se generaría automáticamente. Entonces, ¿cuánto durará Haskell? Bueno, Lisp todavía está con nosotros y no parece que vaya a desaparecer pronto. Haskell es de código abierto BSD3 y ha logrado una masa crítica. Si la programación en sí sigue existiendo dentro de 50 años, esperaría que Haskell, o alguna evolución continua de Haskell, todavía esté aquí.

Actualización 2 en respuesta a la publicación de rvirding

De acuerdo: la implementación de una máquina virtual universal completa "Erskell / Haslang" podría no ser absolutamente imposible, pero ciertamente sería muy difícil. Sin embargo, compartir el nivel del recolector de basura como algo así como una máquina virtual, aunque todavía es difícil , suena un orden de magnitud menos difícil para mí. En el modelo de recolección de basura, los lenguajes funcionales deben tener mucho en común: la desigualdad de los datos inmutables (incluidos los thunk) y el requisito de asignación muy rápida. De modo que el hecho de que las características comunes se agrupen estrechamente con máquinas virtuales monolíticas parece algo extraño.

Las máquinas virtuales ayudan a lograr masa crítica. Basta con ver cómo los lenguajes funcionales ''lite'' como F # y Scala han despegado. Es posible que Scala no tenga la tolerancia absoluta a errores de Erlang, pero ofrece una ruta de escape para la gran cantidad de gente que está vinculada a la JVM.

Si bien tener un solo montón hace que el mensaje pase muy rápido, introduce una serie de otros problemas, principalmente que hacer un GC se vuelve más difícil ya que tiene que ser interactivo y no interrumpir globalmente, por lo que no se pueden usar los mismos algoritmos más simples que el procesar el modelo de pila.

Absolutamente, eso tiene perfecto sentido para mí. Las personas muy inteligentes en el equipo de desarrollo de GHC parecen estar tratando de resolver parte del problema con un GC paralelo "stop the world".

http://research.microsoft.com/en-us/um/people/simonpj/papers/parallel-gc/par-gc-ismm08.pdf

(Obviamente "detener al mundo" no volaría para el general Erlang dado su caso de uso principal.) Pero incluso en los casos de uso donde "detener al mundo" está bien, sus aceleraciones no parecen ser universales. Así que estoy de acuerdo contigo, es poco probable que exista un GC universalmente mejor, que es la razón por la que especifiqué en la parte 1. de mi pregunta que

El tiempo de ejecución de GHC podría configurarse para usar solo un núcleo, o todos los núcleos en la máquina local, o cualquier combinación intermedia.

De esa manera, para un caso de uso dado, podría, después de la evaluación comparativa, elegir ir por el camino de Erlang, ejecutar un tiempo de ejecución de GHC (con un GC monocatenario) más un proceso de Erlang por núcleo y dejar que Erlang copie la memoria entre núcleos para una buena localidad .

Alternativamente, en una máquina de procesador dual con 4 núcleos por procesador con un buen ancho de banda de memoria en el procesador, la evaluación comparativa puede sugerir que ejecute un tiempo de ejecución de GHC (con un GC paralelo) más un proceso de Erlang por procesador.

En ambos casos, si Erlang y GHC pudieran compartir un montón, el intercambio probablemente estaría ligado a un único subproceso del sistema operativo que se ejecuta en un solo núcleo de alguna manera. (Estoy saliendo de mi profundidad aquí, por eso hice la pregunta).

También tengo otra agenda: comparar los lenguajes funcionales independientemente de GC. A menudo leo los resultados de los puntos de referencia de OCaml v GHC v Erlang v ... y me pregunto cuánto se confunden los resultados con los diferentes GC. ¿Qué pasa si la elección de GC puede ser ortogonal a la elección del lenguaje funcional? ¿Qué tan caro es GC de todos modos? Ver esta publicación de blog de los defensores del diablo

http://john.freml.in/garbage-collection-harmful

por mi amigo de Lisp, John Fremlin, que, con encanto, le ha dado su título de publicación "La recolección automática de basura es basura". Cuando John afirma que el GC es lento y no se ha acelerado tanto, me gustaría poder contar algunos números.


Aunque este es un hilo muy antiguo, si los lectores aún están interesados, vale la pena echarle un vistazo a Cloud Haskell , que aporta la simultaneidad del estilo de Erlang y su distribución al GHC estable.

La próxima biblioteca de distributed-process-platform agrega soporte para construcciones OTP-esque como gen_servers, árboles de supervisión y varias otras abstracciones "con sabor a haskell" tomadas de Erlang / OTP.


Como dizzyd mencionó en su comentario, no se copian todos los datos en los mensajes, existen binarios grandes fuera del montículo del proceso y no se copian.

El uso de una estructura de memoria diferente para evitar tener montones separados por proceso es ciertamente posible y se ha llevado a cabo en varias implementaciones anteriores. Si bien tener un solo montón hace que el mensaje pase muy rápido, introduce una serie de otros problemas, principalmente que hacer un GC se vuelve más difícil ya que tiene que ser interactivo y no interrumpir globalmente, por lo que no se pueden usar los mismos algoritmos más simples que el procesar el modelo de pila.

Siempre que usemos estructuras de datos inmutables, no hay problemas con la solidez y la seguridad. Decidir qué memoria y qué modelos de GC utilizar es una gran compensación, y desafortunadamente existe el mejor modelo universal.

Mientras que Haskell y Erlang son ambos lenguajes funcionales, en muchos aspectos son idiomas muy diferentes y tienen implementaciones muy diferentes. Sería difícil encontrar una máquina "Erskell" (o Haslang) que pudiera manejar ambos idiomas de manera eficiente. Personalmente creo que es mucho mejor mantenerlos separados y asegurarnos de que tenga una interfaz realmente buena entre ellos.


Mucha gente de Haskell y Erlang está interesada en el modelo en el que Erlang supervisa la distribución, mientras que Haskell ejecuta los nodos de memoria compartida en paralelo haciendo todos los cálculos numéricos / lógica.

Un comienzo para esto es la biblioteca de Haskell-erlang: http://hackage.haskell.org/package/erlang

Y tenemos esfuerzos similares en la tierra de Ruby, a través de Hubris: http://github.com/mwotton/Hubris/tree/master

La pregunta ahora es encontrar a alguien que realmente empuje a través de la interoperabilidad de Erlang / Haskell para descubrir los asuntos complicados.


Tendrás un momento interesante mezclando GC entre Haskell y Erlang. Erlang utiliza un montón por proceso y copia los datos entre los procesos, ya que Haskell ni siquiera tiene un concepto de procesos, no estoy seguro de cómo trazar este GC "universal" entre los dos. Además, para un mejor rendimiento, Erlang usa una variedad de asignadores, cada uno con comportamientos ligeramente ajustados que estoy seguro afectarían al subsistema GC.

Como con todas las cosas en el software, la abstracción tiene un costo. En este caso, sospecho que tendrías que introducir tantas capas para obtener los dos idiomas por encima de la impedancia de impedancia que terminarías con una máquina virtual común no muy eficiente (o útil).

En resumen, abrace la diferencia! Hay grandes ventajas de NO ejecutar todo en el mismo proceso, especialmente desde el punto de vista de la confiabilidad. Además, creo que es un poco ingenuo esperar que un idioma / máquina virtual te dure para el resto de tu vida (a menos que tengas un plan.) Vivir un corto tiempo o b) convertirse en una especie de monje de código que SOLO funciona en un proyecto único). El desarrollo de software se trata de agilidad mental y estar dispuesto a utilizar las mejores herramientas disponibles para crear un código rápido y confiable.


El CLR admite la optimización de llamadas de cola con un código de operación de tail explícito (como lo utiliza F #), que la JVM no (todavía) tiene un equivalente, lo que limita la implementación de dicho estilo de lenguaje. El uso de AppDomain s por separado permite que CLR intercambie código en caliente (ver, por ejemplo, esta publicación de blog que muestra cómo se puede hacer).

Con Simon Peyton Jones trabajando en el pasillo de Don Syme y el equipo de F # en Microsoft Research, sería una gran decepción si finalmente no viéramos un IronHaskell con algún tipo de estado oficial. Un IronErlang sería un proyecto interesante: la mayor parte del trabajo probablemente sería portar el programador de subprocesos verdes sin ser tan pesado como el motor de flujo de trabajo de Windows, o tener que ejecutar una máquina virtual BEAM sobre el CLR.