2010-08-04 24 views
11

Una implementación fiel de la semántica de paso de mensajes del actor significa que los contenidos del mensaje se copian profundamente desde un punto de vista lógico, incluso para tipos inmutables. La copia profunda de los contenidos de los mensajes sigue siendo un cuello de botella para las implementaciones del modelo de actor, por lo que para el rendimiento algunas implementaciones admiten el envío de mensajes de copia cero (aunque sigue siendo una copia profunda desde el punto de vista del programador).¿Erlang siempre copia mensajes entre procesos en el mismo nodo?

¿Está implementada la copia de mensaje cero-copia en total en Erlang? Entre los nodos obviamente no se puede implementar como tal, pero ¿qué ocurre con los procesos en el mismo nodo? This question está relacionado.

Respuesta

7

AFAIK hubo/hay soporte experimental para la transferencia de mensajes de copia cero en erlang usando el modo -shared o -hybrid. Leí una publicación de blog en 2009 afirmando que está rota en máquinas smp, pero no tengo idea sobre el estado actual

21

No creo que su afirmación sea correcta: la copia profunda de mensajes entre procesos no es correcta. un cuello de botella en Erlang, y con la configuración/compilación VM predeterminada, esto es exactamente lo que están haciendo todos los sistemas Erlang.

Los montones de procesos de Erlang están completamente separados unos de otros, y la cola de mensajes se encuentra en el montón de procesos, por lo que los mensajes deben copiarse. Esto también es cierto para transferir datos dentro y fuera de las tablas de ETS ya que sus datos se almacenan en un área de asignación separada de montones de procesos.

Sin embargo, hay varias estructuras de datos compartidas. Los binarios grandes (> 64 bytes de longitud) se asignan generalmente en un área de todo el nodo y se cuentan como referencia. Los procesos de Erlang solo almacenan referencias a estos binarios. Esto significa que si crea un binario grande y lo envía a otro proceso, solo está enviando la referencia.

Enviar datos entre procesos es en realidad peor en términos de tamaño de asignación de lo que pueda imaginarse: el uso compartido dentro de un término no se conserva durante la copia. Esto significa que si construye cuidadosamente un término con uso compartido para reducir el consumo de memoria, se expandirá a su tamaño no compartido en el otro proceso. Puede ver un ejemplo práctico en OTP Efficiency Guide.

Como señaló Nikolaus Gradwohl, había un modo de pila híbrida experimental para la máquina virtual que permitía el intercambio de términos entre procesos y permitía la transmisión de mensajes de copia cero. No es un experimento particularmente prometedor, como yo lo entiendo, requiere bloqueo adicional y complica la capacidad existente de los procesos para recolectar basura de forma independiente. Por lo tanto, copiar los mensajes entre procesos no es el cuello de botella habitual en los sistemas Erlang, sino que realmente reduce el rendimiento.

+1

Sí, los modelos híbridos y compartidos eran factibles en VM no SMP, pero debido a un bloqueo excesivo y problemas con la recolección de basura en SMP, estos modelos eran extremadamente lentos y difíciles de mantener, por lo que se descartaron. – gleber

4

escribí la respuesta aceptada a esa otra pregunta que está haciendo referencia, y en ella le dan un puntero directo a esta línea de código:

message = copy_struct(message, msize, &hp, &bp->off_heap); 

Esto es en una función llamada cuando el plazo de Erlang el sistema de tiempo debe enviar un mensaje, y no está dentro de ningún tipo de "si" que pueda causar que se salte. Entonces, hasta donde puedo decir, la respuesta es "sí, siempre está copiada". (Eso no es estrictamente cierto; hay un "si", pero parece tratarse de casos excepcionales, no de la ruta de flujo de código normal.)

(Estoy ignorando la opción de montón híbrido presentada por Nikolaus Parece que tiene razón, pero como esta no es la forma en que normalmente se construye Erlang y tiene sus propias sanciones, no veo que valga la pena considerarlo como una forma de responder a su inquietud.)

No sé por qué estás considerando 10 GByte/s un cuello de botella, sin embargo. Nada menos que los registros o el caché de la CPU va más rápido en la computadora, y esos recuerdos son pequeños, constituyendo así una especie de cuello de botella. Además de eso, la idea de copia cero que está proponiendo requeriría bloqueo en el caso de que el mensaje cruzado de la CPU pase en un sistema multi-core, que también es un cuello de botella. Ya estamos pagando la penalización de bloqueo una vez en esta función para copiar el mensaje en la cola de mensajes del otro proceso; ¿Por qué pagarlo de nuevo más tarde cuando el proceso pasa a leer el mensaje?

En pocas palabras, no creo que sus ideas de formas de hacer que sea más rápido en realidad ayudaría mucho.

7

Como se ha mencionado aquí y en otras preguntas, las versiones actuales de Erlang básicamente copian todo excepto los binarios más grandes. En tiempos anteriores a SMP anteriores era factible no copiar, sino pasar referencias. Si bien esto dio como resultado el paso de mensajes muy rápido, creó otros problemas en la implementación, principalmente hizo que la recolección de basura fuera una implementación más difícil y complicada. Creo que hoy el hecho de pasar referencias y compartir datos puede resultar en un bloqueo y sincronización excesivos que, por supuesto, no es algo bueno.

Cuestiones relacionadas