Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List<object> memory overhead

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?

enter image description here enter image description here

EDIT

I've tried to use uint instead of byte[4], but the result is the same: enter image description here

EDIT2

Ok, using uint instead of byte[4] and List<uint>() instead of List<object> put the memory to around 300 MB.

like image 470
ren Avatar asked Apr 05 '17 11:04

ren


People also ask

How much memory does a list take Python?

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.

What is memory overhead?

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.

How do you know what memory an object needs?

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.

What is memory overhead in Python?

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.


1 Answers

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 uints, 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 uints and arrays of bytes.

like image 129
Sergey Kalinichenko Avatar answered Oct 01 '22 13:10

Sergey Kalinichenko