Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

capacity after TrimExcess on List<T>

Tags:

c#

trim access is used minimize a collection's memory For example

 List<string> myList = new List<string>();

If my contain 2 items after trim access capacity of list will be 2

in same manner if list contains 4 or 5 or 6 after TrimExcess capacity turns to 4 or 5 or 6 respectively

But if list contain 3 or 7 or 15 why capacity turns to 4 or 8 or 16 respectively after TrimExcess

Even after this I found one more strange behavior if I run the following code

 List<int> myList = new List<int>();
            for (int i = 1; i <= 100; i++)
            {
                myList.Add(1);
                myList.TrimExcess();
                if (myList.Capacity != myList.Count())
                {
                    var different = myList.Capacity;
                }
            }

if statement get true only if i = 3

Can anyone please let me know the reason

like image 758
slash shogdhe Avatar asked Jan 31 '14 09:01

slash shogdhe


People also ask

What is the capacity of list?

Capacity is the number of elements that the List<T> can store before resizing is required, whereas Count is the number of elements that are actually in the List<T>. Capacity is always greater than or equal to Count.

What is the maximum capacity of list in C#?

List size can be increased up to 2 billion (only when your system works on 64-bit or higher) to store large List<T> objects.

Which method is used to cut off the excess capacity of a list?

Then the TrimExcess method is used to reduce the capacity to match the count, and the Capacity and Count properties are displayed. If the unused capacity had been less than 10 percent of total capacity, the list would not have been resized. Finally, the contents of the list are cleared.

What is initial capacity of a List C#?

The capacity property in ArrayList class gets or sets the number of elements that the ArrayList can contain. The default capacity is 4. If 5 elements are there, then its capacity is doubled and would be 8.


3 Answers

Here's the source code for List<T>:

  public void TrimExcess() {
        int threshold = (int)(((double)_items.Length) * 0.9);
        if( _size < threshold ) {
            Capacity = _size;
        }
    }

Where _size is the backing field for the Count property and _items.Length is what the Capacity getter returns.

So basically, TrimExcess only sets the capacity to Count if more than 10% of the array slots are not being used. That's why in some of your tests Count doesn't equal Capacity.


Another question from the comments:

   1     List<int> myList = new List<int>
   2         {
   3             1,2,3,4,5,6,7 // equivalent to calling `Add` 7 times
   4         };
   5     Console.WriteLine(myList.Capacity); // prints 8 
   6     myList.TrimExcess();
   7     Console.WriteLine(myList.Capacity); // prints 8

Why does line 5 print 8? An empty list starts out with 0 Capacity.

  • When the first element is inserted, Capacity increases to 4, its default capacity.
  • When the fifth element is inserted, Capacity increases to double the current capacity. So if capacity is still 4, it goes up to 8.
  • When the 9th element is inserted, Capacity is doubled again, and so on.

So, when you inserted the 5th element, capacity went from 4 to 8. If you insert two more elements, you'll see the capacity going from 8 to 16.

Why does line 7 print 8?

This was already answered in the first part of my answer.

Now we know why Capacity is 8 before calling TrimExcess. And because there's less than 10% unused space* in the array, TrimExcess does nothing, and Capacity remains 8.

Note: Actually, there's 12.5% unused space (1 free slot / 8 possible slots in the array). But because 7 * 0.9 is rounded to an integer, the threshold becomes 7. And because 7 < 7 returns false, nothing happens.

like image 79
dcastro Avatar answered Oct 20 '22 00:10

dcastro


Taken from msdn-Documentation on List.TrimExcess:

The cost of reallocating and copying a large List can be considerable, however, so the TrimExcess method does nothing if the list is at more than 90 percent of capacity. This avoids incurring a large reallocation cost for a relatively small gain.

This means, that in most cases your List.TrimExcess() call does nothing, and thus there is a difference between List.Count and List.Capacity

like image 20
Vogel612 Avatar answered Oct 20 '22 02:10

Vogel612


I didn't know the reason but I decided to find out:

public void TrimExcess()
{
    int num = (int) (this._items.Length * 0.9);
    if (this._size < num)
    {
        this.Capacity = this._size;
    }
}

That was surprising to me. It only trims the capacity of the collection if more than 10% space is wasted. Seems like a clever optimization for the common case (which is developers calling TrimExcess when they shouldn't...).

Trim yourself:

list.Capacity = list.Size;

It turns out this behavior is even documented.

like image 1
usr Avatar answered Oct 20 '22 02:10

usr