2009-04-02 18 views
5

Struktura obiektu wydaje się używać nadmiernej ilości pamięci podczas wstawiania nowych obiektów do bazy danych.Użycie pamięci struktury encji

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(); 

W tym miejscu obiekty te zawierają bardzo mało elementów danych. Podczas wstawiania 140 000 tych obiektów do bazy danych, całkowite wykorzystanie pamięci aplikacji wyniosło 600 MB, a 1,2 gigabajta na 300 000. Te obiekty są małe, tylko nazwa ciągu i klucz całkowity.

Mogę zmniejszyć zużycie pamięci poprzez umieszczanie połączeń SaveChanges w pętli, ale czas wykonania staje się znacznie gorszy i jest już dość zły.

Ktoś wie dlaczego Entity Framework używa tak dużo pamięci, czyli jak pozbyć się go używać mniej pamięci?

Odpowiedz

2

Ponieważ ramy jednostka przechowuje dane w pamięci (jak wielu ORM użytkownika), a następnie jak w wielu kolekcjach w pamięci prawdopodobnie istnieją tablice wewnętrzne. Gdy dodajesz elementy do kolekcji, wewnętrzna tablica zwiększa się dwukrotnie.

Na przykład, jeśli posiadasz kolekcję taką, jak ArrayList zawierającą 256 elementów i dodajesz do niej 257 pozycję, to co się dzieje wewnętrznie, nowy blok pamięci jest przydzielany dla tablicy 512 elementów, to jest 256 elementów tablicy skopiowane do nowej tablicy 512 elementów, a następnie udostępniona zostanie tablica 256 elementów do usuwania śmieci. Tak więc w momencie przejścia będziesz mieć 768 elementów przydzielonych do pamięci tylko dlatego, że dodałeś 257. przedmiot. Wpadłem w bóle głowy, kiedy używam memorystreamu, ponieważ potrzebujesz prawie 3 razy więcej nieporuszonej pamięci niż to, czego naprawdę potrzebujesz. Jest to właściwość .Capacity widoczna w kolekcjach, a prawie zawsze ma ona moc 2 (ponieważ w razie potrzeby dwukrotnie się zwiększa).

Mój zakład jest tam są tablice wewnętrzne że podwójne wielkości ile potrzeba, aby wesprzeć swoje zbiory w obiektach pamięci. Tak więc 300 000 obiektów tego samego rodzaju prawdopodobnie zostałoby przetrzymane w wewnętrznej tablicy o rozmiarze 524,288. Dodatkowo, jeśli jest podobny do podobnych technik w innym miejscu w .NEt Framework, to za każdym razem, gdy dodano 262145 element, zarówno tablica 262144 jak i 524288 istniała w pamięci, podczas gdy elementy zostały skopiowane do nowej tablicy. Łącznie 786432 elementów w pamięci. Stara tablica będzie się trzymać, dopóki śmieciarz nie zdecyduje, że nie jest już potrzebna.

W strukturze Entity mogą występować pewne opcje dotyczące obsługi współbieżności, które można wyłączyć, co może poprawić wykorzystanie pamięci. Spekuluję tylko tutaj, ale aby obsługiwać współbieżność, przechowują w pamięci zarówno bieżącą wersję danych, jak i jej oryginalną wersję do porównania z obsługą współbieżności.

Chciałbym również spojrzeć na filtrowanie jakie dane są interakcji z. Spróbuj znaleźć sprytne kryteria, aby ograniczyć to, co jest pytaniem i załadowane do pamięci. Na przykład, jeśli masz aplikację, która pozwoliła użytkownikowi edytować konta klientów, ale tylko niektóre konta zostały do ​​nich przypisane, użyj jej jako kryteriów filtrowania, aby załadować tylko do pamięci te konta, z którymi użytkownik mógłby potencjalnie wchodzić.

1

Twoje obiekty mogą być "małe" pod względem rzeczywistych danych, ale każdy obiekt nie jest DTO - Entity Framework dołącza wiele kodów do każdego z twoich obiektów, co oznacza, że ​​rzeczywisty rozmiar każdego obiektu jest całkiem duży.

Jeśli konsekwentnie pracujesz z dużymi wykresami obiektów, rozważ użycie czegoś takiego jak NHibernate, który jest stabilny, dojrzały i sprawdzony w działaniu. Entity Framework jest bardzo daleko w tyle pod względem cech i wydajności.

2

wiem, jest to stara sprawa, ale przeżywa ten sam problem i dziś udało się dowiedzieć, co było przyczyną tego!

Wygląda na to, że generowanie skryptów SQL jest odpowiedzialne za duży skok w pamięci. Zauważyłem, że tworzenie procedur przechowywanych i łączenie ich z moimi obiektami (ale upewnij się, że zwracasz wartość identyfikatorów, jak pokazano w this article), zapisało mi ponad 300 MB pamięci.

Powiązane problemy