para - pruebe java
Java en 2011: conectores roscados VS NIO: ¿qué elegir en el sistema operativo de 64 bits y la última versión de Java? (5)
Lo que a menudo se pasa por alto es que NIO permite el manejo de cero copias. Por ejemplo, si escucha el mismo tráfico de multidifusión desde varios procesos utilizando sockets de la vieja escuela en un único servidor, cualquier paquete de multidifusión se copia desde el búfer de red / kernel a cada aplicación de escucha. Entonces, si construyes una GRID de, por ejemplo, 20 procesos, obtienes problemas de ancho de banda de memoria. Con nio puede examinar el búfer entrante sin tener que copiarlo en el espacio de la aplicación. Luego, el proceso copia solo partes del tráfico entrante que le interesa.
otro ejemplo de aplicación: ver http://www.ibm.com/developerworks/java/library/j-zerocopy/ para ver un ejemplo.
He leído varias publicaciones sobre java.net vs java.nio aquí en StackOverflow y en algunos blogs. Pero aún no puedo tener una idea de cuándo debería uno preferir NIO a los conectores roscados. ¿Puedes por favor examinar mis conclusiones a continuación y decirme cuáles son incorrectas y cuáles se pierden?
Dado que en el modelo con subprocesos debe dedicar un subproceso a cada conexión activa y cada subproceso lleva como 250 kilobytes de memoria para su pila, con el subproceso por modelo de socket se agotará rápidamente la memoria en una gran cantidad de conexiones simultáneas. A diferencia de NIO.
En los sistemas operativos y procesadores modernos, una gran cantidad de hilos activos y el tiempo de cambio de contexto se pueden considerar casi insignificantes para el rendimiento
El rendimiento de NIO puede ser menor porque select () y poll () utilizados por las bibliotecas de NIO asíncronas en entornos de alta carga es más costoso que el despertar y poner hilos de espera.
NIO siempre ha sido más lento, pero le permite procesar más conexiones simultáneas. Básicamente se trata de una compensación de tiempo / espacio: la IO tradicional es más rápida pero tiene una huella de memoria más pesada, NIO es más lenta pero utiliza menos recursos.
Java tiene un límite estricto por subprocesos concurrentes de 15000/30000 según JVM y esto limitará el subproceso por modelo de conexión a este número de conexiones simultáneas como máximo, pero JVM7 no tendrá dicho límite (no puede confirmar esta información).
Entonces, como conclusión, puedes tener esto:
- Si tiene decenas de miles de conexiones simultáneas, NIO es una mejor opción a menos que una velocidad de procesamiento de solicitudes sea un factor clave para usted
- Si tiene menos que eso, el hilo por conexión es una mejor opción (dado que puede permitirse la cantidad de RAM para mantener las acumulaciones de todos los subprocesos concurrentes hasta el máximo)
- Con Java 7 es posible que desee revisar NIO 2.0 en cualquier caso.
¿Estoy en lo correcto?
Me parece correcto, excepto por la parte sobre Java que limita el número de subprocesos, que normalmente está limitado por el sistema operativo en el que se ejecuta (ver ¿Cuántos subprocesos puede admitir una máquina virtual Java? Y no puede obtener 2542 subprocesos en Java en 4 GB iMac OSX 10.6.3 Snow Leopard (32 bits) ).
Para llegar a esa cantidad de hilos probablemente necesitará ajustar el tamaño de la pila de la JVM.
No hay una sola "mejor" forma de construir servidores NIO, ¡pero la preponderancia de esta pregunta en particular en SO sugiere que la gente piense que sí existe! Su pregunta resume los casos de uso que se adaptan a ambas opciones lo suficientemente bien para ayudarlo a tomar la decisión que sea adecuada para usted.
¡Además, las soluciones híbridas también son posibles! Podrías entregar el canal a los hilos cuando van a hacer algo digno de su costo, y mantenerte en NIO cuando sea mejor.
Sigo pensando que el cambio de contexto general para los hilos en IO tradicional es significativo. En un nivel alto, solo obtiene rendimiento utilizando varios subprocesos si no compiten por los mismos recursos, o pasan mucho más tiempo que la sobrecarga del cambio de contexto en los recursos. La razón para sacar esto a relucir es con nuevas tecnologías de almacenamiento como SSD, sus hilos vuelven a contender en la CPU mucho más rápido
Yo diría que empiece con hilo por conexión y se adapte desde allí si tiene problemas.
Si realmente necesita manejar un millón de conexiones, debería considerar escribir (o encontrar) un agente de solicitud simple en C (o lo que sea) que utilizará mucha menos memoria por conexión que cualquier implementación de Java. El intermediario puede recibir solicitudes de forma asincrónica y ponerlas en cola para respaldar a los trabajadores escritos en el idioma de su elección.
Por lo tanto, los backends solo necesitan un hilo por solicitud activa, y puede tener un número fijo de ellos para que la memoria y el uso de la base de datos estén predeterminados hasta cierto punto. Cuando se ejecutan grandes cantidades de solicitudes en paralelo, las solicitudes se hacen esperar un poco más.
Por lo tanto, creo que nunca debería tener que recurrir a los canales de selección de NIO o de E / S asincrónicas (NIO 2) en los sistemas de 64 bits. El modelo de subproceso por conexión funciona lo suficientemente bien y puede ampliar su escala a "decenas o cientos de miles" de conexiones utilizando alguna tecnología de bajo nivel más apropiada.
Siempre es útil evitar la optimización prematura (es decir, escribir código NIO antes de que realmente haya un gran número de conexiones entrando) y no reinventar la rueda (Jetty, nginx, etc.) si es posible.