Sto scrivendo alcuni software "big data" che devono contenere molti dati in memoria. Ho scritto un prototipo in C++ che funziona alla grande. Tuttavia, gli utenti finali in genere codificano in Java, quindi mi hanno chiesto di scrivere anche un prototipo java.ottimizzazione della dimensione in memoria java
Ho fatto una lettura di fondo su memoria-footprint in java e alcuni test preliminari. Ad esempio, Diciamo che ho questo oggetto
public class DataPoint{
int cents, time, product_id, store_id;
public DataPoint(int cents, int time, int product_id, int store_id){
this.cents = cents;
this.time = time;
this.product_id = product_id;
this.store_id = store_id;
}
}
In C++ la sizeof questa struttura è 16 byte, che ha un senso. In Java dobbiamo essere indiretti. Se creo, ad esempio, 10 m di questi oggetti e utilizzo Runtime.totalMemory() - Runtime.freeMemory() prima di e dopo e poi divido a seconda dei casi, ottengo circa 36 byte per struttura. Una differenza di memoria di ~ 2.4 volte è piuttosto sgradevole; diventerà brutto quando proveremo a tenere in memoria centinaia di milioni di DataPoints.
Ho letto da qualche parte che in casi come questo in Java è meglio archiviare i dati come array - essenzialmente un archivio basato su colonne piuttosto che un archivio basato su righe. Penso di capirlo: la modalità basata su colonne riduce il numero di riferimenti e forse la JVM può persino impacchettare intelligentemente le intere in parole da 8 byte.
Quali altri trucchi posso utilizzare per ridurre l'impronta di memoria di ciò che è essenzialmente un blocco di memoria che ha una dimensione molto grande (milioni/miliardi di punti dati) e una dimensione molto piccola (il numero O (1) di colonne/variabili)?
Risulta archiviare i dati come 4 int array utilizzati esattamente 16 byte per voce. La lezione: piccoli oggetti hanno un overhead proporzionale sgradevole in java.
totalMemory include anche la memoria libera, prova a misurare con totalMemory() - freeMemory() – Henry
Prima di tutto se si desidera una figura veramente accurata, fare un dump dell'heap dell'applicazione e aprire tale dumping con qualcosa come Memory Analyzer (http : //www.eclipse.org/mat/) per ottenere una cifra accurata. 2nd - qual è il modello di accesso a questi dati? forse puoi guadagnare più headroom usando una libreria cache in grado di distribuire porzioni inutilizzate su disco? dì dividi i tuoi punti in matrici di oggetti da 10K e archivia questi "blocchi" in infinispan (http://www.jboss.org/infinispan/) o simili? – radai
@Henry Buon punto! Misurare con totalMemory() - freeMemory() dà un valore di 36 byte per struttura. Meglio di 52, ma ancora> 2x quello di C++. – andyInCambridge