ListObject-Speicheraufwand

8

Ich habe so etwas:

%Vor%

Jetzt ist val immer Byte [4] und es gibt ungefähr 37000000 Elemente. Also würde ich denken, dass res etwa 37 * 10 ^ 6 * 4 Bytes = 148 MB sein sollte, aber die tatsächliche Speicherbelegung beträgt etwa 2 GB. Wenn ich res.Add(val); kommentiere, dann ist die Speicherbelegung irgendwo 100 MB.

Wohin geht also die Erinnerung?

BEARBEITEN

Ich habe versucht, anstelle von Byte [4] uint zu verwenden, aber das Ergebnis ist dasselbe:

EDIT2

Ok, mit uint anstelle von Byte [4] und List<uint>() anstelle von List<object> setzen Sie den Speicher auf etwa 300 MB.

    
ren 05.04.2017, 11:04
quelle

1 Antwort

7

Dies ist ein häufiges Problem bei der Zuweisung großer Mengen winziger Objekte: Der Objekt-Overhead, den Sie normalerweise ignorieren können, kommt ins Spiel.

  

37 * 10 ^ 6 * 4 Bytes = 148 MB

Angenommen, ein Array von vier Bytes würde vier Bytes im Speicher belegen, ist falsch. Zusätzlich zu der Nutzlast von vier Bytes muss das Array-Objekt die Länge des Arrays, einen Sync-Block und einen Typzeiger speichern. Dies ergibt 12 Byte Overhead bei einem 32-Bit-System oder 24 Byte bei einem 64-Bit-System.

Zusätzlich zu den individuellen Gemeinkosten von Array-Objekten müssen Sie den Overhead des Speicherzuordners, den Overhead der Speicherausrichtung und den Overhead des Garbage Collector berücksichtigen. Alles zusammen genommen, ist es nicht unvernünftig zu sehen, dass die gesamte verwendete Speicherkapazität auf 2 GB anwächst.

Eine Möglichkeit, dies zu beheben, besteht darin, zu einer Liste von uint s zu wechseln, die jeweils vier Bytes belegen. Wenn Sie vier Bytes speichern müssen, konvertieren Sie sie in uint und speichern Sie sie in der Liste. Wenn Sie Ihre Bytes zurück benötigen, konvertieren Sie uint in ein temporäres Vier-Byte-Array. Verwenden Sie BitConverter mit der Konvertierung zwischen uint s und Arrays von byte s umzugehen.

    
dasblinkenlight 05.04.2017, 11:19
quelle

Tags und Links