2009-09-29 5 views
20

AFAIK, la memoria in Java è basata su heap da cui la memoria è assegnata agli oggetti in modo dinamico e non vi è alcun concetto di memoria condivisa.Qualsiasi concetto di memoria condivisa in Java

Se non esiste un concetto di memoria condivisa, la comunicazione tra i programmi Java dovrebbe richiedere molto tempo. In C, dove la comunicazione tra processi è più veloce tramite la memoria condivisa rispetto ad altre modalità di comunicazione.

Correggimi se sbaglio. Inoltre, qual è il modo più veloce per comunicare con i 2 prog di Java.

+0

Intendi "in C dove la comunicazione con memoria condivisa è più veloce ..."? – Will

+0

Sì, ha modificato la domanda –

risposta

14

Poiché non esiste un'API ufficiale per creare un segmento di memoria condivisa, è necessario ricorrere a una libreria helper/DDL e JNI per utilizzare la memoria condivisa in modo che due processi Java comunichino tra loro.

In pratica, questo è raramente un problema poiché Java supporta i thread, quindi è possibile eseguire due "programmi" nella stessa Java VM. Quelli condivideranno lo stesso heap, quindi la comunicazione sarà istantanea. Inoltre non è possibile ottenere errori a causa di problemi con il segmento di memoria condivisa.

+1

Questo è cambiato da Java 7. Java ora ha file mappati in memoria. – Arkadiy

+2

@Arkadiy: file ** mappati in memoria ** sono stati aggiunti con Java 1.4 con NIO. Java 7 lo ha esteso con NIO 2. Ma OP vuole sapere della memoria ** condivisa **, che è un concetto diverso. –

+3

Sebbene la memoria condivisa sia effettivamente un concetto diverso, i file mem-mapped possono essere utilizzati in modo un po 'simile per IPC. E sì, hai ragione su Java 1.4 :) – Arkadiy

7

La memoria condivisa a volte è veloce. A volte non è così - danneggia le cache della CPU e la sincronizzazione è spesso un problema (e dovrebbe fare affidamento su mutex e simili, può essere una penalizzazione delle prestazioni).

Barrelfish è un sistema operativo che dimostra che IPC che utilizza il trasferimento di messaggi è in realtà più veloce della memoria condivisa all'aumentare del numero di core (sulle architetture X86 convenzionali e sul materiale NUCA NUMA più esotico che si supponeva fosse destinato al targeting) .

Quindi la tua ipotesi che la memoria condivisa sia veloce richiede test per il tuo particolare scenario e sul tuo hardware di destinazione. Non è un'ipotesi sonora generica in questi giorni!

+4

Questo è fuorviante. Le scritture contese danneggiano le prestazioni, bloccando le prestazioni. Le letture condivise aiutano le prestazioni e la memoria condivisa supera l'IPC con una buona implementazione (infatti, i migliori sistemi IPC sono implementati con memoria condivisa). Uso del kernel L'IPC è orribile per le prestazioni. Così, mentre ha il suo posto ed è concettualmente più facile da lavorare, le prestazioni non sono sicuramente un motivo per usare IPC! – Eloff

4

Ci sono un paio di tecnologie comparabili mi viene in mente:

  1. Alcuni anni fa c'era una tecnologia chiamata JavaSpaces ma che non è mai veramente sembrava prendere piede, un peccato se mi chiedete.
  2. Oggigiorno ci sono le tecnologie di cache distribuita, cose come Coherence e Tangosol.

Purtroppo né avrà la velocità fuori proprio di memoria condivisa, ma lo fanno affrontare i problemi di accesso simultaneo, ecc

7

Una cosa da guardare è utilizzando memory-mapped files, utilizzando Java NIO's FileChannel classe o simili (vedi il metodo map()). Lo abbiamo usato con molto successo per comunicare (nel nostro caso a senso unico) tra un processo Java e uno nativo C sulla stessa macchina.

Ammetto che non sono un esperto di filesystem (per fortuna ne abbiamo uno sul personale!) Ma le prestazioni per noi sono assolutamente incredibilmente veloci - in effetti si sta trattando una sezione della cache della pagina come un file e leggere + scrivere direttamente senza il sovraccarico delle chiamate di sistema. Non sono sicuro delle garanzie e della coerenza - ci sono metodi in Java per forzare le modifiche da scrivere nel file, il che implica che sono (a volte? Tipicamente? Normalmente? Normalmente? Non sicuro) scritte nel file sottostante reale (un po '? molto? estremamente?) pigramente, il che significa che una parte del tempo è fondamentalmente solo un segmento di memoria condivisa.

In teoria, a quanto ho capito, i file mappati in memoria POSSONO essere effettivamente supportati da un segmento di memoria condiviso (sono solo handle di file, penso) ma non sono a conoscenza di un modo per farlo in Java senza JNI.

+0

thread piuttosto vecchio, ma mi chiedevo se è possibile commentare le prestazioni di velocità (latenza) del metodo rispetto ai normali socket TCP/IP?Ho cercato un modo per migliorare la latenza tra 2 app (una java, una C/C++), attualmente comunicate tramite socket ... – Bastien

+1

Quasi certamente non troverai più nulla di un file mappato in memoria. Le scritture sul file, anche in posizioni casuali, sono fondamentalmente solo delle scritture sulla memoria principale (che è la cosa più veloce che puoi fare). La questione delle "regole" di Java su quando scaricare il file system sottostante è per me aperta, dato che non l'ho visto documentato + non ho guardato la fonte. Posso dirvi che stavamo facendo molte centinaia, probabilmente migliaia, di piccole (1-4 byte) di scritture al file al secondo, in posizioni casuali, e mai notato nulla di simile a un problema di prestazioni. – Cowan

+2

Questo thread è ancora più vecchio ora, ma puoi consultare https://github.com/peter-lawrey/Java-Chronicle Questo raggiunge 5-20 milioni di messaggi al secondo * persistito * con una latenza unidirezionale di meno di 200 ns tra processi. –

22

Ci sono almeno 2 modi per farlo - RAM Drive o Apache APR.

Dettagli here e here con alcune misurazioni delle prestazioni.

+0

Vorrei +5 questa risposta invece di fare +1. Questi due articoli sono interessanti e pratici. E rispondi alla domanda originale. –

9

Il progetto di Peter Lawrey Java Chronicle vale la pena guardare.

Questi sono some tests che avevo fatto qualche tempo fa confrontando varie opzioni off-heap e on-heap.

+0

Anche https://github.com/OpenHFT/Chronicle-Queue e https://github.com/OpenHFT/Chronicle-Map utilizzano la memoria condivisa. –

0

Le informazioni fornite da Cowan sono corrette. Tuttavia, anche la memoria condivisa non sembra sempre identica in più thread (e/o processi) allo stesso tempo. Il motivo alla base della chiave è il modello di memoria Java (che è costruito sul modello di memoria hardware). Vedi Can multiple threads see writes on a direct mapped ByteBuffer in Java? per una discussione abbastanza utile sull'argomento.

1

Simile a Java Chronicle di Peter Lawrey, puoi provare a Jocket.

Utilizza anche un MappedByteBuffer ma non mantiene alcun dato ed è pensato per essere utilizzato come sostituzione drop-in su Socket/ServerSocket.

La latenza di roundtrip per un ping-pong da 1 kB è di circa mezzo microsecondo.

2

Il modo più semplice per farlo è quello di avere due processi che istanziano lo stesso file mappato in memoria. In pratica condivideranno lo stesso spazio di memoria off-heap. Puoi prendere l'indirizzo fisico di questa memoria e usare sun.misc.Unsafe per scrivere/leggere le primitive. Supporta la concorrenza attraverso i metodi putXXXVolatile/getXXXVolatile. Dai uno sguardo allo CoralQueue che offre IPC facilmente così come la comunicazione tra thread all'interno della stessa JVM.

Disclaimer: Sono uno degli sviluppatori di CoralQueue.

1

MappedBus (http://github.com/caplogic/mappedbus) è una libreria che ho aggiunto su github che abilita l'IPC tra più (più di due) processi/JVM Java passando il messaggio.

Il trasporto può essere un file mappato in memoria o una memoria condivisa. Per usarlo con la memoria condivisa basta seguire gli esempi nella pagina di github ma puntare i lettori/scrittori su un file sotto "/ dev/shm /".

È open source e l'implementazione è completamente spiegata nella pagina github.