2010-05-06 36 views
5

Ich habe einen Teil des Codes, der auf großen Arrays von double (mit mindestens etwa 6000 Elemente) und führt mehrere hundert Mal (in der Regel 800).Speicherlecks während der Verwendung von Doppel-Array

Wenn I Standard-Schleife verwenden, wie folgt aus:

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

der Speicherverbrauch steigt für etwa 40 MB (von 40 MB im beggining der Schleife am Ende der 80 MB).

Wenn ich erzwinge, den Garbage Collector bei jeder Iteration auszuführen, bleibt die Speicherbelegung bei 40 MB (der Anstieg ist nicht signifikant).

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

Aber die Ausführungszeit ist 3 mal länger! (es ist entscheidend)

Wie kann ich die C# zwingen, den gleichen Bereich des Speichers zu verwenden, anstatt neue zuzuweisen? Hinweis: Ich habe Zugriff auf den Code someObject Klasse, also wenn es erforderlich wäre, kann ich es ändern.

+1

Ich würde gerne sehen, was Sie mit dem Array tun, nachdem Sie es erhalten und wie die producesOutput funktioniert, wenn möglich. –

Antwort

7

Warum reservieren Sie eine große, leere 10 nur um sie zu überschreiben? Vielleicht sollten Sie das Array übergeben, damit seine Werte an Ort und Stelle geändert werden. Dies würde es Ihnen ermöglichen, es wiederzuverwenden.

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

Wenn die Methode manchmal weniger als 6000 Elemente füllt, könnte sie einfach die Füllzahl zurückgeben. Alternativ können Sie eine List<double> verwenden, die Größenänderung ermöglicht.

+0

Es scheint die Lösung war so einfach ..;) Danke! Es klappt. – Gacek

+0

Froh, dass unser Rat geholfen hat. –

3

Machen singleRow ein Parameter und gibt es in den Aufruf zu producesOutput jedes Mal ...

Grundsätzlich Ihre producesOutput Methode wahrscheinlich wird jedes Mal einer neuen Array-Zuweisung und die Neuzuordnung von singleRow markiert nur die alten Speicher wie verfügbar zu entfernen, aber den GC aus Leistungsgründen nicht ausgeführt.

+1

Keine Notwendigkeit, es zu einem ref machen, wenn das Array von fester Länge ist. –

+0

Das stimmt. Danke für die Erinnerung :) –

+1

Wohl würde 'ref' keinen direkten Schaden verursachen und würde die Absicht zeigen, den Parameter zu modifizieren. Trotzdem glaube ich nicht, dass es das Richtige ist. –

0

Sie werden das nicht mögen, aber wenn Sie GC erzwingen müssen, tun Sie etwas falsch. Denken Sie daran, dass die Erinnerung wachsen kann, bis Druck auf einen GC ausgeübt wird - das ist eine GUTE Sache, denn das bedeutet, dass GC nicht läuft, bis es notwendig ist.

Hier ist ein albern klingender Test, aber es könnte etwas Licht in das Geschehen bringen. Innerhalb von FillWithOutput() kommentieren Sie die meisten Funktionen aus. Dann führe deine Schleife aus und vermesse Memeory. Teilen Sie Teile davon schrittweise auf, bis Sie einen Blip sehen. Jetzt nähern Sie sich dem, was das "Leck" verursacht.

+0

Ich denke, die Quelle des "Lecks" ist schon ziemlich klar. –

Verwandte Themen