Búfer de protocolo de primer uso de alta latencia

Yanick Salzmann:

En una de nuestras aplicaciones java que tenemos un buen número de clases de búfer de protocolo y el frasco de esencia expone una interfaz con un método que es utilizado por otra aplicación. Nos hemos dado cuenta que la primera vez que este método se denomina tiempo de invocación es bastante alta (> 500 ms), mientras que las llamadas posteriores son mucho más rápidos (<10 ms). Al principio se asumió que esto tiene algo que ver con nuestro código, sin embargo después de perfiles que no pudimos confirmar esto. A través de un proceso de eliminación se hizo evidente que tiene algo que ver con búferes de protocolo.

Esto se confirmó cuando en una aplicación diferente, que las obras completamente diferentes - pero también utiliza búferes de protocolo - mostraron el mismo comportamiento. Además hemos intentado crear una instancia ficticia ( XY.newBuilder().build()) de todas las clases de amortiguamiento del proto en el arranque y con cada uno de los añadimos pudimos notar la sobrecarga de la primera gota invocación.

En .NET puedo encontrar otra pregunta que muestra el problema similar ( ¿Por qué es tan lento protobuf en la primera llamada, pero muy rápido dentro de los bucles? ), Sin embargo la solución no parece ser específico para C # con serializadores Precompilar. No pude encontrar el mismo problema en Java hasta el momento. ¿Hay soluciones provisionales como el que se muestra en la pregunta anterior que se aplican a java?

Charles Dowbecki:

JVM se envía con compilador Just-In-Time (JIT), que hace un montón de optimización de su código. Puede cavar en partes internas de JVM, si se quiere entender más a fondo. Habrá carga de clases y descarga, perfiles de rendimiento, compilación de código y descompilación, cierre parcial, etc.

Para dar un ejemplo de cómo esto puede ser complejo, de acuerdo con este artículo , en OpenJDK hay dos compiladores (C1 y C2) con cinco posibles niveles de compilación de código:

compilación escalonado tiene cinco niveles de optimización. Se inicia en el nivel de 0, el nivel de intérprete, en donde la instrumentación proporciona información sobre los métodos críticos de rendimiento. Muy pronto el nivel 1, el simple compilador C1 (cliente), optimiza el código. En el Nivel 1, no hay información de perfiles. A continuación viene el nivel 2, donde se compilan sólo unos pocos métodos (de nuevo por el compilador cliente). En el nivel 2, para los pocos métodos, información de perfil se reunieron para la entrada-contadores y ramas de alimentación de bucle. Nivel 3 sería entonces ver todos los métodos de conseguir compilados por el compilador cliente información completa de perfiles, y finalmente el nivel 4 de acogerse a C2, el compilador servidor.

La lección aquí es que si usted requiere un rendimiento predecible que siempre debe WARMUP su código mediante la ejecución de algunas peticiones ficticias después de cada despliegue.

Usted hizo lo correcto con el maniquí código de la creación de todos los objetos usados ​​protobuff pero se debe dar un paso más allá y el método real de calentamiento que está golpeando.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=361949&siteId=1
Recomendado
Clasificación