2009-04-02 32 views
5

Il framework entità sembra utilizzare quantità eccessive di memoria quando si inseriscono nuovi oggetti in un database.Utilizzo memoria quadro entità

for(int i = 0; i < numOwners; ++i) 
{ 
    var owner = Owner.CreateOwner(); 
    db.AddToOwnerSet(owner); 
    for(int j = 0; j < numChildren; ++j) 
    { 
     var child = Child.CreateChild(); 
     owner.Childs.Add(child); 
    } 
} 
db.SaveChanges(); 

A questo punto, questi oggetti contengono pochissimi elementi di dati. Quando si inseriscono 140.000 di questi oggetti nel database, l'utilizzo della memoria totale dell'applicazione era di 600 MB e 1,2 gigabyte per 300.000. Questi oggetti sono piccoli, solo un nome di stringa e una chiave intera.

Posso ridurre l'utilizzo della memoria inserendo le chiamate di SaveChanges nel ciclo, ma i tempi di esecuzione peggiorano notevolmente, ed è già piuttosto brutto.

Qualcuno sa perché il framework di entità sta usando così tanta memoria, o come ottenerlo per usare meno memoria?

risposta

2

Poiché il framework entità mantiene i dati in memoria (come fanno molti ORM), quindi come in molte raccolte in memoria ci sono probabilmente array interni. Man mano che si aggiungono elementi a una raccolta, l'array interno raddoppia la capacità.

Ad esempio, se si dispone di una raccolta come ArrayList contenente 256 elementi e si aggiunge il 257 ° elemento, allora ciò che accade internamente è un nuovo blocco di memoria allocato per un array di elementi 512, l'array di 256 elementi è copiato nel nuovo array di elementi 512 e quindi l'array di 256 elementi è reso disponibile per la garbage collection. Quindi nel punto di transizione avrai 768 oggetti allocati in memoria solo perché hai aggiunto il 257 ° elemento. Ho riscontrato mal di testa durante l'utilizzo di memorystream, perché hai bisogno di una memoria non frammentata contigua di quasi il triplo di quella di cui hai veramente bisogno. Questa è la proprietà .Capacity che vedi nelle collezioni, ed è quasi sempre una potenza di 2 (dal momento che raddoppia di dimensioni secondo necessità).

La mia scommessa è che ci sono matrici interne che raddoppiano in base alle esigenze per supportare le raccolte di oggetti in memoria. Quindi 300.000 oggetti dello stesso tipo verrebbero probabilmente conservati in una matrice interna di dimensioni 524.288. Inoltre, se è simile a tecniche simili altrove nel .NEt Framework, allora ogni volta che veniva aggiunto l'elemento 262145th, entrambi gli array 262144 e 524288 erano presenti in memoria mentre gli elementi venivano copiati nel nuovo array. Un totale di 786432 oggetti in memoria. Il vecchio schieramento rimarrebbe in piedi fino a quando il garbage collector non decise che non era più necessario.

Nel framework Entity potrebbero esserci alcune opzioni relative al supporto della concorrenza che è possibile disabilitare e che potrebbero migliorare l'utilizzo della memoria. Tuttavia, qui sto solo speculando, ma per supportare la concorrenza memorizzano in memoria sia l'attuale versione dei dati, sia la versione originale per il confronto per supportare la concorrenza.

Vorrei anche filtrare i dati con cui stai interagendo. Cerca di trovare criteri intelligenti per limitare ciò che viene richiesto e caricato in memoria. Ad esempio, se disponi di un'applicazione che consente a un utente di modificare gli account dei clienti, ma solo alcuni account sono stati assegnati a loro, quindi utilizzali come criteri di filtro in modo che tu carichi solo in memoria gli account con cui l'utente potrebbe potenzialmente interagire.

1

Gli oggetti potrebbero essere "piccoli" in termini di dati effettivi, ma ogni oggetto non è un DTO - il Entity Framework allega un sacco di codice boilerplate a ciascuna delle entità, il che significa che la dimensione effettiva di ciascun oggetto è piuttosto grande.

Se si lavora costantemente con grafici a oggetti di grandi dimensioni, è consigliabile utilizzare qualcosa come NHibernate, stabile, maturo e collaudato. Entity Framework è molto indietro in termini di caratteristiche e prestazioni.

2

So che questa è una domanda vecchia ma stavo vivendo lo stesso problema oggi e sono riuscito a scoprire cosa lo stava causando!

Sembrerebbe che la generazione degli script SQL è responsabile per il grande salto in memoria. Ho scoperto che la creazione di stored procedure e il loro collegamento ai miei oggetti (ma assicurati di restituire il valore per gli ID come mostrato in this article) mi ha salvato più di 300mb di memoria.

Problemi correlati