2013-05-28 12 views
7

La mia domanda riguarda la misura in cui un'applicazione JVM può sfruttare il layout NUMA di un host.NUMA awareness di JVM

Ho un'applicazione Akka in cui gli attori contemporaneamente trattino le richieste combinando i dati in ingresso con i dati 'comuni' già caricati in un (Scala) oggetto immutabile. L'applicazione si adatta bene al cloud, utilizzando molte macchine virtuali dual core, ma funziona male su un singolo 64 core. Presumo questo perché l'oggetto dati comune risiede in una cella NUMA e molti thread che accedono contemporaneamente da altre celle è troppo per le interconnessioni.

Se corro 64 applicazioni JVM separati contenenti ciascuno 1 attore quindi prestazioni è è ancora buona. Un approccio più moderato potrebbe essere quello di eseguire tante applicazioni JVM quante sono le celle NUMA (8 nel mio caso), dando al sistema operativo host la possibilità di tenere insieme i thread e la memoria?

Ma c'è un modo più intelligente per ottenere lo stesso effetto all'interno di una singola JVM? Per esempio. se sostituissi il mio oggetto dati comune con diverse istanze di una classe case, la JVM avrebbe la possibilità di posizionarle sulla cella NUMA ottimale?

Aggiornamento:

Sto utilizzando Oracle JDK 1.7.0_05 e Akka 2.1.4

ora ho provato con le opzioni UseNUMA e UseParallelGC JVM. Nessuno dei due sembrava avere un impatto significativo sulle prestazioni lente quando si utilizza una o poche JVM. Ho anche provato a usare un PinnedDispatcher e il thre-pool-executor senza alcun effetto. Non sono sicuro che la configurazione stia avendo un effetto, dal momento che non sembra esserci nulla di diverso nei log di avvio.

Il miglioramento maggiore rimane quando utilizzo una singola JVM per worker (~ 50). Tuttavia, il problema con questo sembra essere che c'è un lungo ritardo (fino a un paio di minuti) prima che FailureDector registri lo scambio riuscito di "primo battito" tra le JVM del cluster Akka. Sospetto che ci sia un altro problema qui che non ho ancora scoperto. Ho già dovuto aumentare l'ulimit -u poiché stavo colpendo il numero massimo predefinito di processi (1024).

tanto per chiarire, non sto cercando di raggiungere un gran numero di messaggi, solo cercando di avere un sacco di attori separati accedere contemporaneamente un oggetto immutabile.

+2

Stai utilizzando l'opzione -XX: + UseNUMA jvm? – cmbaxter

+0

Inoltre, quali impostazioni del GC utilizzi? E quale esecutore config? –

+0

Probabilmente devi dire ad akka di usare migliori schemi di threading, vedi qui per alcune opzioni di configurazione della casella di posta: http://doc.akka.io/docs/akka/snapshot/scala/dispatchers.html – Noah

risposta

2

penso che se sei sicuro che i problemi non in algoritmi di elaborazione dei messaggi, allora si dovrebbe prendere in considerazione non solo l'opzione della NUMA, ma tutta l'ENV. configurazione, a partire dalla versione JVM (l'ultima è migliore, Oracle JDK funziona anche meglio di OpenJDK) poi le opzioni JVM (inclusi GC, memoria, opzioni di concorrenza ecc.) quindi versioni di Scala e Akka (ultimi candidati e pietre miliari possono essere molto migliori) e anche la configurazione di Akka.

Da here è possibile prendere in prestito tutto ciò che conta per ottenere 50M messages per second of total throughput for Akka actors on contemporary laptops.

Non abbiamo mai avuto la possibilità di eseguire questi parametri di riferimento su server a 64-core - così qualsiasi feedback sarà molto apprezzato.

Dalle mie conclusioni, che possono essere d'aiuto, le attuali implementazioni di ForkJoinPool aumentano la latenza di invio dei messaggi quando il numero di thread nel pool aumenta. È molto evidente nei casi in cui il tasso di risposta-richiesta di chiamata tra attori è elevato, e. g. sul mio portatile quando si aumentano le dimensioni del pool da 4 a 64, la latenza di invio degli attori Akka per tali casi cresce fino a 2-3 volte per la maggior parte dei servizi di esecuzione (Scala ForkJoinPool, JDK's ForkJoinPool, ThreadPoolExecutor).

È possibile verificare se ci sono differenze eseguendo mvnAll.sh con la variabile di sistema benchmark.parallelism impostata su valori diversi.

+0

Ecco un post sul blog che descrive il profilo di scalabilità di akka sul nostro server di test 48 core utilizzando FJP: http://letitcrash.com/post/20397701710/50-million-messages-per-second-on-a-single-machine –