Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory usage of an empty List or Dictionary?

Tags:

c#

memory

How much memory is used by an empty List or Dictionary? Such as:

List<double> list = new List<double>();

The pointer itself eats at least 32 bits on x86 and 64 of x64 OS, but what about the list itself? With 0 records.

The reason for asking is, can you save some bytes by setting lists to null?

(Imagine you have a class that contains some List<T> which in some cases is being used and in other case it is not, in that case having a boolean like IsEmpty and null instead of empty list might save some operating memory. Especially in case you would have thousands of such classes in operating memory, every bit counts.)

like image 641
Petr Avatar asked Apr 21 '13 13:04

Petr


People also ask

Which takes more memory list or dictionary?

Dictionary occupies much more space than a list of tuples.

Does an empty list take up memory?

An empty list takes 56 bytes, but each additional int adds just 8 bytes, where the size of an int is 28 bytes. A list that contains a long string takes just 64 bytes. The answer is simple.

How much memory does a dictionary use Python?

In other words, our dictionary, with nothing in it at all, consumes 240 bytes. Not bad; given how often dictionaries are used in Python, it's good to know that they don't normally consume that much memory.

How much memory does a dictionary use C#?

200 * 20 = 4000 bytes for each top level dictionary. How many of those do you have? You say 10's of thousands of them in thousand of objects. Every 10,000 is going to consume about 38 MB of dictionary overhead.


1 Answers

Decompiled by dotPeek :

public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable
{
    private T[] _items; //4 bytes for x86, 8 for x64
    private int _size; //4 bytes
    private int _version; //4 bytes
    [NonSerialized]
    private object _syncRoot; //4 bytes for x86, 8 for x64
    private static readonly T[] _emptyArray; //one per type
    private const int _defaultCapacity = 4; //one per type
    ...
}

you got total of 20 bytes on x86 (16 for List<T> members and 4 for metadata reference overhead) and 32 on x64, including reffernce to type of the object, which each object in .net have. This calculation is done roughly not counting alligment.


public class Dictionary<TKey, TValue> : ...
{
    private int[] buckets; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.Entry[] entries; //4 bytes for x86, 8 for x64
    private int count; //4 bytes
    private int version; //4 bytes
    private int freeList; //4 bytes
    private int freeCount; //4 bytes
    private IEqualityComparer<TKey> comparer; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.KeyCollection keys; //4 bytes for x86, 8 for x64
    private Dictionary<TKey, TValue>.ValueCollection values; //4 bytes for x86, 8 for x64
    private object _syncRoot; //4 bytes for x86, 8 for x64

    private const string VersionName = "Version"; //one per type
    private const string HashSizeName = "HashSize"; //one per type
    private const string KeyValuePairsName = "KeyValuePairs"; //one per type
    private const string ComparerName = "Comparer"; //one per type
}

44 for x86 and 72 for x64. Again rough calculation, since instances of different objects are required.

like image 131
Ilya Ivanov Avatar answered Sep 25 '22 22:09

Ilya Ivanov