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.
When you create a list object, the list object by itself takes 64 bytes of memory, and each item adds 8 bytes of memory to the size of the list because of references to other objects.
In computer science, overhead is any combination of excess or indirect computation time, memory, bandwidth, or other resources that are required to perform a specific task.
getsizeof() function can be done to find the storage size of a particular object that occupies some space in the memory. This function returns the size of the object in bytes. It takes at most two arguments i.e Object itself.
Thus memory usage for a normal object has three sources: The normal overhead of any Python object, be it instance, integer, or what have you, plus the overhead of an empty dictionary. The overhead of storing entries in the dictionary. The actual data being added as attributes.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With