我正在嘗試向 List 添加大量資料,但它似乎比陣列使用了更多的 RAM。我想知道為什么會這樣,是否有更好的解決方案。
這個帶有陣列的解決方案需要大約 78 MB 的 RAM。有意義,因為 4 位元組 * 20000000 ~= 76 MB:
float[] arrayValues = new float[20000000];
for (int i = 0; i < 20000000; i )
arrayValues[i] = i;
但是這個帶有串列的解決方案需要 206 MB (!!):
List<float> listValues = new();
for (int i = 0; i < 20000000; i )
listValues.Add(i);
怎么可能?它基本上做同樣的事情 - 保存 20000000 個浮點值。額外的 128 MB 來自哪里?是否有更好的方法不會產生如此多的開銷?
uj5u.com熱心網友回復:
當您將Add新專案放入 a 時,List<T>它必須進行記憶體重新分配,以便為這些新專案提供足夠的空間。讓我們來看看這個程序:
List<float> listValues = new();
int capacity = listValues.Capacity;
for (int i = 0; i < 20000000; i ) {
listValues.Add(i);
if (capacity != listValues.Capacity) {
capacity = listValues.Capacity;
Console.WriteLine(capacity);
}
}
結果:
4
8
16
32
64
128
256
512
1024
2048
4096
8192
16384
32768
65536
131072
262144
524288
1048576
2097152
4194304
8388608
16777216
33554432 // <- Finally, list allocates memory for 33554432 items
如您所見,現在33554432專案已分配并且4 8 16 ... 16777216是垃圾。在最壞的情況下,我們已經
33554432分配了物品和33554432垃圾物品;總的來說33554432 33554432 = 67108864 ~ 3 * 20000000,您可以看到這3 個因素。
你能做什么?
指定Capacity以避免重新分配(典型解決方案):
// We can avoid all this mess with reallocations
// by specifing required capacity: 20000000 items in our case
List<float> listValues = new(20000000);
for (int i = 0; i < 20000000; i ) {
listValues.Add(i);
}
測量前收集所有垃圾:
// Business as usual
List<float> listValues = new();
for (int i = 0; i < 20000000; i ) {
listValues.Add(i);
}
// Collect garbage to measure real List efficency:
// List allocates 33554432 items vs. 20000000 in case of array
// About ~70% overhead
GC.Collect(2);
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/367478.html
