streams latest performance scala jvm akka low-latency

performance - latest - Trading de alta frecuencia en la JVM con Scala/Akka



akka latest (3)

Imaginemos un hipotético sistema HFT en Java, que requiere (muy) baja latencia, con muchos objetos pequeños de corta duración debido a la inmutabilidad (Scala?), Miles de conexiones por segundo y un número obsceno de mensajes que pasan en una Arquitectura dirigida por eventos (akka y amqp?).

Para los expertos, ¿cuál sería (hipotéticamente) el mejor ajuste para JVM 7? ¿Qué tipo de código lo haría feliz? ¿Estarían Scala y Akka listos para este tipo de sistemas?

Nota: ha habido algunas preguntas similares, como esta, pero aún tengo que encontrar una que cubra a Scala (que tiene su propia huella idiosincrásica en la JVM).


En mi computadora portátil, la latencia promedio de los mensajes de ping entre los actores Akka 2.3.7 es de ~300ns y es mucho menor que la latencia esperada debido a las pausas de GC en las JVM.

Código (incl. Opciones de JVM) y resultados de pruebas para Akka y otros actores en Intel Core i7-2640M here .

PS Puede encontrar muchos principios y consejos para la computación de baja latencia en el site Dmitry Vyukov y en el blog Martin Thompson.


Es posible lograr muy buen rendimiento en Java. Sin embargo, la pregunta debe ser más específica para proporcionar una respuesta creíble. Sus principales fuentes de latencia provendrán de la siguiente lista no exhaustiva:

  1. Cuánta basura creas y el trabajo del CG para recolectarla y promoverla. En mi experiencia, los diseños inmutables no encajan bien con baja latencia. La afinación GC debe ser un gran foco.

  2. Calienta la JVM para que las clases se carguen y el JIT haya tenido tiempo de hacer su trabajo.

  3. Diseñe sus algoritmos para que sean O (1) o al menos O (log2 n), y realice pruebas de rendimiento que lo confirmen.

  4. Su diseño debe estar libre de bloqueos y seguir el " Principio de escritor único ".

  5. Es necesario hacer un esfuerzo significativo para comprender todo el conjunto y mostrar simpatía mecánica en su uso.

  6. Diseñe sus algoritmos y estructuras de datos para que sean fáciles de almacenar en caché. El caché perdido en estos días es el mayor costo. Esto está estrechamente relacionado con la afinidad del proceso que, si no se configura correctamente, puede resultar en una contaminación significativa de la memoria caché. Esto implicará simpatía por el sistema operativo e incluso algún código JNI en algunos casos.

  7. Asegúrese de tener suficientes núcleos para que cualquier subproceso que deba ejecutarse tenga un núcleo disponible sin tener que esperar.

Recientemente hice un blog sobre un estudio de caso de un ejercicio de este tipo.


Es posible que el uso de un búfer de anillo para el paso de mensajes supere lo que se puede hacer con Akka. La implementación principal del búfer de anillo que la gente usa en la JVM para aplicaciones financieras es una llamada Disruptor que se ajusta cuidadosamente para la eficiencia (potencia de dos tamaños), para la JVM (sin GC, sin bloqueos) y para las CPU modernas (sin compartir falsamente líneas de caché).

Aquí hay una presentación de introducción desde el punto de vista de Scala http://scala-phase.org/talks/jamie-allen-sdisruptor/index.html#1 y hay enlaces en la última diapositiva al material original de LMAX.