2010-05-06 14 views
5

Mam część kodu, która działa na dużych tablicach o wartości double (zawierającej co najmniej 6000 elementów) i wykonuje kilkaset razy (zwykle 800).Wycieki pamięci przy użyciu macierzy podwójnej

Kiedy użyciu standardowego pętli tak:

double[] singleRow = new double[6000]; 
int maxI = 800; 
for(int i=0; i<maxI; i++) 
{ 
singleRow = someObject.producesOutput(); 
//... 
// do something with singleRow 
// ... 
} 

punkt Pamięć wzrasta użycia do około 40 MB (z 40 MB na początku działalności pętli, do 80 MB na końcu).

Kiedy zmuszam do korzystania z garbage collector do wykonania przy każdej iteracji, wykorzystanie pamięci pozostaje na poziomie 40MB (wzrost jest nieistotny).

double[] singleRow = new double[6000]; 
int maxI = 800; 
for(int i=0; i<maxI; i++) 
{ 
singleRow = someObject.producesOutput(); 
//... 
// do something with singleRow 
// ... 
GC.Collect() 
} 

Ale czas wykonania jest 3 razy dłuższy! (jest to kluczowe)

Jak zmusić C# do korzystania z tego samego obszaru pamięci zamiast przydzielania nowych? Uwaga: Mam dostęp do kodu klasy someObject, więc jeśli będzie to potrzebne, mogę to zmienić.

+1

Chciałbym zobaczyć, co robisz z tablicą po jej uzyskaniu i jak działa productionOutput, jeśli to możliwe. –

Odpowiedz

7

Dlaczego przydzielacie duże, puste singleRow tylko po to, aby je zastąpić? Być może powinieneś przekazać tablicę, aby zmodyfikować jej wartości. To pozwoli ci na ponowne użycie.

double[] singleRow = new double[6000]; 
int maxI = 800; 
for(int i=0; i<maxI; i++) 
{ 
    someObject.FillWithOutput(singleRow); 
    //... 
    // do something with singleRow 
    // ... 
} 

Jeśli metoda czasami wypełnia mniej niż 6000 elementów, może po prostu zwrócić liczbę wypełnień. Alternatywnie możesz użyć parametru List<double>, który umożliwi zmianę rozmiaru.

+0

Wygląda na to, że rozwiązanie było takie proste ..;) Dzięki! To działa. – Gacek

+0

Cieszę się, że nasza rada pomogła. –

3

Bądź singleRow parametru a przekazać je do wywołania producesOutput za każdym razem ...

Zasadniczo metoda producesOutput jest prawdopodobnie przydzielenie nowej tablicy za każdym razem, i ponowne przypisanie singleRow tylko znaki stary pamięć jako dostępna do usunięcia, ale nie uruchamia GC ze względu na wydajność.

+1

Nie ma potrzeby, aby był to ref, jeśli tablica ma stałą długość. –

+0

To prawda. Dzięki za przypomnienie :) –

+1

Prawdopodobnie 'ref' nie spowodowałoby żadnej szkody bezpośredniej i wskazywałoby na zamiar zmodyfikowania parametru. Mimo to nie sądzę, że jest to słuszne. –

0

Nie spodoba ci się to, ale jeśli musisz zmusić GC, robisz coś nie tak. Pamiętaj, że pamięć może rosnąć, dopóki nie pojawi się presja wyzwolenia GC - jest to DOBRA, ponieważ oznacza to, że GC nie działa, dopóki nie musi.

Oto głupio brzmiący test, ale może rzucić trochę światła na to, co się dzieje. Wewnątrz FillWithOutput() komentuje większość swoich funkcji. Następnie uruchom pamięć i zmień pamięć. Inkrementuj i usuwaj komentarze, dopóki nie zobaczysz blipu. Teraz zbliżasz się do tego, co powoduje "wyciek".

+0

Myślę, że źródło "wycieku" jest już całkiem jasne. –

Powiązane problemy