问题
I have something like this:
List<object> res = new List<object>();
...
while (...)
{
byte[] val = //get new byte[4]
res.Add(val); //if this is commented memory usage goes from 2Gb to 180Mb
}
return res;
Now val
is always byte[4] and there are around 37000000 elements. So I would think that res
should be around 37*10^6 * 4 bytes = 148 MB, but the real memory usage is around 2GB. If I comment res.Add(val);
then memory usage is somewhere 100 MB.
So where does the memory go to?
EDIT
I've tried to use uint instead of byte[4], but the result is the same:
EDIT2
Ok, using uint instead of byte[4] and List<uint>()
instead of List<object>
put the memory to around 300 MB.
回答1:
This is a common problem of allocating large amounts of tiny objects: object overhead, which you can usually disregard, comes into play.
37*10^6 * 4 bytes = 148 Mb
Assuming that an array of four bytes would occupy four bytes in memory is incorrect. In addition to the payload of four bytes, array object must store array's length, a sync block, and a type pointer. This works out to 12 bytes of overhead on a 32-bit system, or 24 bytes on a 64-bit system.
In addition to individual overheads of array objects you need to factor in the overhead of memory allocator, overhead of memory alignment, and overhead of garbage collector. All things taken together, it is not unreasonable to see the total memory in use grow to 2 Gb.
One way to fix this is to switch to a list of uint
s, which do occupy four bytes each. When you need to store four bytes, convert them to uint
, and store it in the list. When you need your bytes back, convert uint
into a temporary four-byte array. Use BitConverter to deal with converting between uint
s and arrays of byte
s.
来源:https://stackoverflow.com/questions/43229348/listobject-memory-overhead