2012-10-31 21 views
12

Stiamo migrando un'applicazione ActivePivot a un nuovo server (4 socket Intel Xeon, 512 GB di memoria). Dopo la distribuzione, abbiamo lanciato il nostro benchmark applicativo (che è un mix di grandi query OLAP concomitanti alle transazioni in tempo reale). Le prestazioni misurate sono quasi due volte più lente rispetto al nostro server precedente, che ha processori simili ma due volte meno core e due volte meno memoria.In che modo l'architettura NUMA influisce sulle prestazioni di ActivePivot?

Abbiamo esaminato le differenze tra i due server e sembra che il grande abbia un'architettura NUMA (memoria non uniforme). Ogni socket della CPU è fisicamente vicino a 1/4 della memoria, ma più lontano dal resto ... La JVM che esegue la nostra applicazione alloca un grande heap globale, c'è una frazione casuale di quell'heap su ciascun nodo NUMA. La nostra analisi è che il pattern di accesso alla memoria è piuttosto casuale e i core della CPU spesso sprecano tempo ad accedere alla memoria remota.

Abbiamo bisogno di più feedback su come sfruttare ActivePivot sui server NUMA. Possiamo configurare i cubi di ActivePivot o i pool di thread, modificare le nostre query, configurare il sistema operativo?

risposta

13

Peter ha descritto le opzioni generali JVM disponibili oggi per ridurre l'impatto sulle prestazioni delle architetture NUMA. Per farla breve, una JVM con conoscenza NUMA ripartirà l'heap rispetto ai nodi NUMA e quando un thread crea un nuovo oggetto, l'oggetto viene allocato nel nodo NUMA del core che esegue quel thread (se lo stesso thread utilizza in seguito esso, l'oggetto sarà nella memoria locale). Inoltre, durante la compattazione dell'heap, la JVM con conoscenza NUMA evita lo spostamento di grandi blocchi di dati tra i nodi (e riduce la durata degli eventi stop-the-world).

Quindi su qualsiasi hardware NUMA e per qualsiasi applicazione Java l'opzione -XX: + UseNUMA dovrebbe probabilmente essere abilitata.

Ma per ActivePivot questo non aiuta molto: ActivePivot è un database in memoria. Ci sono aggiornamenti in tempo reale ma la maggior parte dei dati risiede nella memoria principale per tutta la vita dell'applicazione. Indipendentemente dalle opzioni JVM, i dati verranno suddivisi tra i nodi NUMA ei thread che eseguono le query accederanno alla memoria casualmente. Sapendo che la maggior parte delle sezioni del motore di query di ActivePivot vengono eseguite velocemente quanto la memoria può essere recuperata, l'impatto NUMA è particolarmente visibile.

Quindi, come ottenere il massimo dalla soluzione ActivePivot su un hardware NUMA?

Esiste una soluzione semplice quando l'applicazione ActivePivot utilizza solo una frazione delle risorse (rileviamo che accade spesso quando più soluzioni ActivePivot vengono eseguite sullo stesso server). Ad esempio una soluzione ActivePivot che utilizza solo 16 core su 64 e 256 GB su un TeraByte. In tal caso, è possibile limitare il processo JVM stesso a un nodo NUMA.

Su Linux precedere il lancio JVM con la seguente opzione (http://linux.die.net/man/8/numactl):

numactl --cpunodebind=xxx 

Se l'intero server è dedicato a una soluzione ActivePivot, è possibile sfruttare l'ActivePivot Distributed Architecture per partizionare i dati. Se sono presenti 4 nodi NUMA, si avviano 4 JVM che ospitano 4 nodi ActivePivot, ciascuno associato al relativo nodo NUMA. Con questa distribuzione le query vengono distribuite tra i nodi e ciascun nodo eseguirà la propria parte del lavoro alla massima prestazione, all'interno del nodo NUMA corretto.

+0

Quando si utilizza numactl, si consiglia di utilizzare lo switch '--membind = nodes, -m nodes' in aggiunta a' --cpunodebind = nodes, -N nodes' per limitare la memoria a quel nodo. Altrimenti una piccola parte della memoria viene solitamente allocata su nodi stranieri (anche con '-XX: + UseNUMA') –

5

Puoi provare a utilizzare -XX:+UseNUMA

http://docs.oracle.com/javase/7/docs/technotes/guides/vm/performance-enhancements-7.html

Se ciò non produce il risultato che ci si aspetta che si potrebbe essere necessario utilizzare taskset per bloccare una JVM ad una presa specifica ed efficace rompere il server in quattro macchine con una JVM ciascuna.

Ho notato che la macchina con più socket ha un accesso più lento alla loro memoria (anche la loro memoria locale) e come sempre ti dà i guadagni di prestazioni che vuoi come risultato.

Problemi correlati