2009-09-29 17 views
20

AFAIK, la memoria en Java se basa en el montón desde el cual la memoria se asigna dinámicamente a los objetos y no existe el concepto de memoria compartida.Cualquier concepto de memoria compartida en Java

Si no existe un concepto de memoria compartida, la comunicación entre los programas Java debería consumir mucho tiempo. En C, donde la comunicación entre procesos es más rápida a través de la memoria compartida en comparación con otros modos de comunicación.

Corrígeme si me equivoco. Además, ¿cuál es la forma más rápida de que 2 progenitores Java hablen entre sí?

+0

¿Quiere decir "en C donde la comunicación de memoria compartida es más rápida ..."? – Will

+0

Sí, modificó la pregunta –

Respuesta

14

Dado que no existe una API oficial para crear un segmento de memoria compartida, debe recurrir a una biblioteca auxiliar/DDL y JNI para usar la memoria compartida para que dos procesos Java se comuniquen entre sí.

En la práctica, esto rara vez es un problema ya que Java admite subprocesos, por lo que puede tener dos "programas" que se ejecutan en la misma máquina virtual de Java. Esos compartirán el mismo montón, por lo que la comunicación será instantánea. Además, no puede obtener errores debido a problemas con el segmento de memoria compartida.

+1

Esto cambió desde Java 7. Java ahora tiene archivos mapeados en la memoria. – Arkadiy

+2

@Arkadiy: Se agregaron ** archivos ** con ** memoria de memoria con Java 1.4 con NIO. Java 7 extendió esto con NIO 2. Pero OP quiere saber acerca de la ** memoria ** compartida, que es un concepto diferente. –

+3

Si bien la memoria compartida es de hecho un concepto diferente, los archivos mem-mapped se pueden usar de una manera similar para IPC. Y sí, tienes razón acerca de Java 1.4 :) – Arkadiy

7

La memoria compartida a veces es rápida. A veces no es así - daña las memorias caché de la CPU y la sincronización es a menudo un dolor (y si se basa en mutexes y tal, puede ser una gran penalización de rendimiento).

Barrelfish es un sistema operativo que demuestra que el IPC utilizando mensajes es más rápido que la memoria compartida a medida que aumenta el número de núcleos (en arquitecturas convencionales X86 y en las cosas NUMA NUCA más exóticas que supongo que estaba apuntando) .

Por lo tanto, su suposición de que la memoria compartida es rápida necesita pruebas para su escenario particular y en su hardware de destino. ¡No es una suposición sonora genérica estos días!

+4

Esto es engañoso. Contended escribe daño rendimiento, bloqueo duele rendimiento. Las lecturas compartidas ayudan a mejorar el rendimiento, y la memoria compartida supera al IPC con una buena implementación (de hecho, los mejores sistemas IPC se implementan con la memoria compartida). Usar kernel IPC es horrible para el rendimiento. Por lo tanto, aunque tiene su lugar y es conceptualmente más fácil trabajar con él, ¡el rendimiento definitivamente no es una razón para usar IPC! – Eloff

4

Hay un par de tecnologías comparables se me ocurre:

  1. Hace unos años hubo una tecnología llamada JavaSpaces pero que realmente nunca parecía a tomar fuerza, una pena si usted me pregunta.
  2. Hoy en día existen las tecnologías de caché distribuida, cosas como Coherence y Tangosol.

Desafortunadamente, ni tendrá la velocidad de salida correcta de memoria compartida, pero que hacen frente a los problemas de acceso concurrente, etc.

7

Una cosa a tener en cuenta es el uso de memory-mapped files, utilizando Java NIO's FileChannel clase o similar (ver el método map()). Hemos utilizado esto con mucho éxito para comunicarnos (en nuestro caso, de una sola dirección) entre un proceso Java y uno C nativo en la misma máquina.

Admitiré que no soy un experto en sistemas de archivos (afortunadamente tenemos uno en el equipo) pero el rendimiento para nosotros es absolutamente increíblemente rápido: efectivamente está tratando una sección de la memoria caché de páginas como un archivo y leyendo + escribiendo directamente sin la sobrecarga de las llamadas al sistema. No estoy seguro acerca de las garantías y la coherencia: hay métodos en Java para forzar los cambios que se escriben en el archivo, lo que implica que (a veces, normalmente, normalmente, normalmente, no seguro) se escriben en el archivo subyacente real. (¿Algo? ¿Muy? ¿Extremadamente?) perezosamente, lo que significa que una proporción del tiempo es básicamente solo un segmento de memoria compartida.

En teoría, según entiendo, los archivos mapeados en memoria PUEDEN estar respaldados por un segmento de memoria compartida (creo que son solo identificadores de archivos), pero no conozco una forma de hacerlo en Java sin JNI.

+0

bastante viejo hilo, pero me preguntaba si puede comentar sobre el rendimiento de velocidad (latencia) de su método en comparación con los zócalos TCP/IP regulares?He estado investigando una forma de mejorar la latencia entre 2 aplicaciones (una Java, una C/C++), comunicándose actualmente a través de sockets ... – Bastien

+1

Es casi seguro que no encontrará nada más rápido que un archivo mapeado en memoria. Las escrituras en el archivo, incluso en posiciones aleatorias, son básicamente escrituras en la memoria principal (que es lo más rápido que puedes hacer). La cuestión de las "reglas" de Java acerca de cuándo ir al sistema de archivos subyacente es una pregunta abierta para mí, ya que no la he visto documentada ni he visto la fuente. Puedo decirte que estábamos haciendo muchos cientos, probablemente miles, de pequeñas escrituras (de 1 a 4 bytes) en el archivo por segundo, en ubicaciones aleatorias, y nunca noté nada remotamente como un problema de rendimiento. – Cowan

+2

Este hilo es incluso más antiguo ahora, pero puede consultar https://github.com/peter-lawrey/Java-Chronicle Esto logra 5-20 millones de mensajes por segundo * persistido * con una latencia de una vía de menos de 200 ns entre procesos. –

22

Existen al menos 2 formas de hacerlo: RAM Drive o Apache APR.

Detalles here y here con algunas medidas de rendimiento.

+0

Me gustaría hacer +5 en esta respuesta en lugar de +1. Esos dos artículos son interesantes y prácticos. Y responde a la pregunta original. –

9

Peter Lawrey's Java Chronicle proyecto vale la pena mirar.

Estos son some tests que había hecho hace un tiempo comparando varias opciones de montón y montón.

+0

También https://github.com/OpenHFT/Chronicle-Queue y https://github.com/OpenHFT/Chronicle-Map usan memoria compartida. –

0

La información proporcionada por Cowan es correcta. Sin embargo, incluso la memoria compartida no siempre parecerá ser idéntica en varios hilos (y/o procesos) al mismo tiempo. La razón subyacente clave es el modelo de memoria de Java (que se basa en el modelo de memoria de hardware). Ver Can multiple threads see writes on a direct mapped ByteBuffer in Java? para una discusión bastante útil del tema.

1

Similar a la Crónica de Java de Peter Lawrey, puede intentar Jocket.

También utiliza un MappedByteBuffer pero no conserva ningún dato y está destinado a ser utilizado como un reemplazo directo a Socket/ServerSocket.

Latencia de ida y vuelta para un ping-pong de 1kB es de aproximadamente medio microsegundo.

2

La manera más fácil de hacerlo es tener dos procesos instanciando el mismo archivo mapeado en memoria. En la práctica, compartirán el mismo espacio de memoria fuera de montón. Puede tomar la dirección física de esta memoria y usar sun.misc.Unsafe para escribir/leer primitivas. Admite concurrencia a través de los métodos putXXXVolatile/getXXXVolatile. Eche un vistazo en CoralQueue que ofrece IPC de manera sencilla, así como la comunicación entre hilos dentro de la misma JVM.

Descargo de responsabilidad: Soy uno de los desarrolladores de CoralQueue.

1

MappedBus (http://github.com/caplogic/mappedbus) es una biblioteca que he agregado en github que permite el IPC entre múltiples (más de dos) procesos/JVM de Java mediante el envío de mensajes.

El transporte puede ser un archivo mapeado en memoria o una memoria compartida. Para usarlo con la memoria compartida, simplemente siga los ejemplos en la página de github, pero apunte a los lectores/escritores a un archivo en "/ dev/shm /".

Es de código abierto y la implementación se explica completamente en la página de github.

Cuestiones relacionadas