2009-04-25 14 views
17

Come si ottimizza l'utilizzo della dimensione heap di un'applicazione che ha molti (milioni) di oggetti longevi? (Grande cache, il caricamento di un sacco di record da un db)Come si rende efficiente la memoria dell'applicazione Java?

  • utilizzare il tipo di dati a destra
    • Evitare java.lang.String per rappresentare altri tipi di dati
  • Evita duplicato oggetti
    • Utilizzare le enumerazioni se i valori sono noti in anticipo
    • Utilizzare pool di oggetti
    • String.Intern() (buona idea?)
  • carico/mantenere solo gli oggetti necessari

Sto cercando per la programmazione generale o risposte specifiche Java. Nessun interruttore del compilatore funky.

Edit:

Ottimizzare la rappresentazione memoria di un POJO che può apparire milioni di volte nel mucchio.

I casi d'uso

  • carico un enorme file CSV in memoria (convertito in POJO)
  • Usa Hibernate per recuperare milioni di record da un database

Curriculum di risposte:

  • Utilizzare il modello di peso vivo
  • Copia su scrittura
  • Invece di caricare oggetti 10M con 3 proprietà, è più efficiente disporre di 3 matrici (o altra struttura dati) di dimensione 10 M? (Potrebbe essere un problema manipolare i dati ma se hai davvero poca memoria ...)
+9

scrivendo il vostro programma in assembly ... :) –

+2

dubito che assembler avrebbe aiutato - i tempi di sviluppo sarebbe significativamente più lungo e non sarebbe cross platform. ;) – Fortyrunner

+3

@Fortyrunner Sospetto che Desmond stia facendo uno scherzo. –

risposta

17

Non dire che tipo di oggetti stai cercando di archiviare, quindi è un po 'difficile da offrire consigli. Tuttavia alcuni (non esclusivo) approcci, in nessun ordine particolare, sono:

  • Utilizzare un possibile flyweight pattern ovunque .
  • Memorizzazione nella cache del disco. Esistono soluzioni di cache numerous per Java.
  • C'è qualche discussione sul fatto che String.intern sia una buona idea. Vedi here per una domanda. String.intern() e la quantità di dibattito attorno alla sua idoneità.
  • Fare uso di soft o weak riferimenti per memorizzare dati che è possibile ricreare/ricaricare su richiesta.Vedere here per informazioni su come utilizzare i riferimenti dinamici con le tecniche di memorizzazione nella cache.

Conoscere meglio gli interni e la durata degli oggetti che si stanno archiviando darebbe una risposta più dettagliata.

+0

Downvoted perché? –

20

Suggerisco di utilizzare un profiler di memoria, vedere dove si sta consumando la memoria e ottimizzarlo. Senza informazioni quantitative potresti finire per cambiare qualcosa che non ha alcun effetto o peggiora le cose.

Si potrebbe guardare la modifica dei dati, specialmente se gli oggetti sono piccoli. Ad esempio, è possibile rappresentare una tabella di dati come una serie di colonne con matrici di oggetti per ogni colonna, anziché un oggetto per riga. Questo può far risparmiare una quantità significativa di spese generali per ogni oggetto se non è necessario rappresentare una singola riga. per esempio. una tabella con 12 colonne e 10.000.000 righe potrebbe utilizzare 12 oggetti (uno per colonna) anziché 10 milioni (uno per riga)

+0

Un buon trucco per ridurre al minimo il numero di oggetti. – Boune

+1

Sono d'accordo che un profiler di memoria è un buon punto di partenza per qualcuno che non sa quali istanze di classe stanno prendendo tutta la memoria. La domanda è più, se so in anticipo avrò 10M pojo # 1 in memoria, come ridurre al minimo il consumo di ogni istanza? – Boune

11

Garantire una buona normalizzazione del modello a oggetti, non duplicare valori.

Ahem, e, se è solo milioni di oggetti Penso che mi piacerebbe semplicemente fare una decente a 64 bit VM e un sacco di RAM;)

+1

Quale è probabilmente la soluzione più conveniente :-) –

+0

+1 - Questo è il nocciolo del problema. – duffymo

+0

Ottima risposta. L'utilizzo di cache di dati e la riduzione di record e campi duplicati è un notevole risparmio. – Fortyrunner

1

voglio aggiungere qualcosa al punto di Peter giá fatto (can 'commenta la sua risposta :() è sempre meglio usare un profiler di memoria (controlla java memory profiler) che passare per intuizione.80% del tempo è la routine che ignoriamo ha qualche problema in esso.anche le classi di raccolta sono più inclini alla memoria perdite.

4

normale "profiler" non vi aiuterà molto, perché avete bisogno di una panoramica di tutti gli oggetti "dal vivo". È necessario mucchio analizzatore discarica. raccomando la Eclipse Memory analyzer.

Verificare la presenza di oggetti duplicati, iniziando con le stringhe. Verifica se puoi applicare modelli come peso vivo, copyonwrite, inizializzazione pigra (google sarà tuo amico).

2

È possibile memorizzare un numero inferiore di oggetti nella memoria. :) Usa una cache che si riversa sul disco o usa Terracotta per raggruppare il tuo heap (che è virtuale) permettendo alle parti inutilizzate di essere scaricate dalla memoria e reinserite in modo trasparente.

0

Uno stravagante: mantenere la maggior parte dei dati compressi nella ram . Espandi solo il set di lavoro corrente. Se i tuoi dati hanno una buona localizzazione che può funzionare bene.

Utilizzare strutture dati migliori. Le raccolte standard in Java sono piuttosto ad uso intensivo di memoria.

[che cosa è una migliore struttura di dati]

  • Se si dà un'occhiata alla fonte per le collezioni, vedrai che se si limitano te stesso nel modo in cui si accede alla raccolta, è possibile risparmiare spazio per elemento
  • Il modo in cui la raccolta gestisce la crescita non è utile per le raccolte di grandi dimensioni. Troppa copia. Per le raccolte di grandi dimensioni, è necessario un algoritmo basato su blocchi, come btree.
+0

Come definiresti le strutture dati migliori? Come lo implementeresti? – Boune

0

Dedica un po 'di tempo alla conoscenza e alla messa a punto dello VM command line options, in particolare quelli relativi alla garbage collection. Anche se questo non cambierà la memoria utilizzata dai tuoi oggetti, può avere un grande impatto sulle prestazioni con app ad alta intensità di memoria su macchine con molta RAM.

1

Se si dispone di milioni di numeri interi e galleggianti ecc poi vedere se gli algoritmi permettono di rappresentare i dati in array di primitive. Ciò significa meno riferimenti e minori costi di CPU per ogni garbage collection.

0
  1. Assign null valore per tutta la variables che sono no longer utilizzati. Quindi make it available for Garbage collection.
  2. De-reference the collections una volta che l'utilizzo è terminato, altrimenti GC non li spazzerà.
+1

Non sono d'accordo con l'articolo 1. Vorrei semplicemente lasciare che il gc faccia quello che si suppone di fare. Ci sono solo pochi casi (array, raccolte) in cui questo potrebbe essere utile, non tutte le variabili. http://stackoverflow.com/questions/449409/does-assigning-objects-to-null-in-java-impact-garbage-collection – Boune

Problemi correlati