Pregunta

Nuestra aplicación está leyendo datos muy rápido a través de sockets TCP/IP en Java. Estamos utilizando la biblioteca NIO con un enchufes sin bloqueo y un selector para indicar la preparación para leer. En promedio, los tiempos generales de procesamiento para leer y manejar los datos de lectura son sub-milisegundos. Sin embargo, con frecuencia vemos picos de 10-20 milisegundos. (Ejecutando en Linux).

Usando tcpdump Podemos ver la diferencia de tiempo entre la lectura de TCPDump de 2 mensajes discretos, y comparar eso con el tiempo de nuestras aplicaciones. Vemos tcpdump Parece no tener retraso, mientras que la aplicación puede mostrar 20 milisegundos.

Estamos bastante seguros de que esto no es GC, porque el registro de GC no muestra prácticamente ningún GC completo, y en JDK 6 (de lo que entiendo) el GC predeterminado es paralelo, por lo que no debería detener los subprocesos de la aplicación (a menos que haga GC completo) .

Parece casi como si hubiera algún retraso para Java's Selector.select(0) método para devolver la preparación para leer, porque en la capa TCP, los datos ya están disponibles para ser leídos (y tcpdump lo está leyendo).

Información adicional: en la carga máxima estamos procesando alrededor de 6,000 x 150 bytes AVG por mensaje, o aproximadamente 900 MB por segundo.

¿Fue útil?

Solución

La colección Eden todavía incurre en una pausa STW, por lo que 20 ms pueden ser perfectamente normales dependiendo del comportamiento de asignación y el tamaño/tamaño del montón del conjunto en vivo.

Otros consejos

¿Se ejecuta su código Java en Rtlinux, o alguna otra distribución con capacidad de programación en tiempo real? Si no, 10-20 ms de jitter en los tiempos de procesamiento parece completamente razonable y esperado.

Tuve el mismo problema en un servicio Java en el que trabajo. Al enviar la misma solicitud repetidamente desde el cliente, el servidor bloquearía en el mismo lugar en la transmisión durante 25-35 ms. Apagando el algoritmo de Nagle en el enchufe me solucionó esto. Esto se puede lograr llamando a SettcPnodelay (verdadero) en el socket. Esto puede dar como resultado una mayor congestión de la red porque los ACK ahora se enviarán como paquetes separados. Ver http://en.wikipedia.org/wiki/nagle%27s_algorithm Para obtener más información sobre el algoritmo de Nagle.

Desde el Preguntas frecuentes de tcpdump:

¿Cuándo está estampado en un paquete? ¿Qué tan precisas son las marcas de tiempo?

En la mayoría de los sistemas operativos en los que se ejecutan TCPDUM y libpCap, el paquete se estampa como parte del proceso del controlador de dispositivos de la interfaz de red, o la pila de redes, manejándolo. Esto significa que el paquete no está estampado en el instante en que llega a la interfaz de red; Después de que el paquete llegue a la interfaz de red, habrá un retraso hasta que se entregue una interrupción o la interfaz de red esté encuestada (es decir, la interfaz de red podría no interrumpir el host de inmediato; el controlador puede configurarse para encuestar la interfaz si la red El tráfico es pesado, para reducir la cantidad de interrupciones y procesar más paquetes por interrupción), y habrá un retraso adicional entre el punto en el que la interrupción comienza a procesarse y se genera la marca de tiempo.

Por lo tanto, lo más probable es que la marca de tiempo se realice en la capa de núcleo privilegiada, y los 20 ms perdidos es para cambiar el contexto sobre el espacio de usuario y en Java y la lógica del selector de red JVMS. Sin más análisis del sistema en su conjunto, no creo que sea posible hacer una selección afirmativa de causa.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top