Rob
Rob

Reputation: 4477

Can I persuade Garbage Collection to truncate a list? An array?

If I have a List that I want to trim to save memory, I seem to be able to set the list capacity and then wait for GC to free the memory. When the List gets promoted to the next generation, the memory allocated for it appears to be a function of the list's capacity, rather than the memory originally allocated. This saves me copying explicitly, and ultimately means 1 less copy in total.

var x = new List<double>(50000000) { 1, 2, 3 };
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used
x.Capacity = 3;
GC.Collect(2);
//Much less memory now used

Is it possible to do the same thing somehow with Arrays?

Note that I don't intend to force GC explicitly - this is just to illustrate that when GC does eventually occur, the memory is freed.

Upvotes: 1

Views: 221

Answers (4)

Jeppe Stig Nielsen
Jeppe Stig Nielsen

Reputation: 61982

Behind the scenes, x.Capacity = 3; or x.TrimExcess() will copy all the entries from the private array that holds them, over to a new tiny array. The huge array will then later be collected.

To do something similar for your own array, you can do:

var y = new double[50000000];
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used

Array.Resize(ref y, 3);

GC.Collect(2);
//Much less memory now used

Doc: Array.Resize<T> method

Upvotes: 1

dcastro
dcastro

Reputation: 68710

Simply use TrimExcess of List<T>.

This is the equivalent of list.Capacity = list.Count, which allocates a new array of size list.Count and copies all the elements to it.

You can use the same strategy for arrays, but you'll have to code it yourself though:

int[] arr = new int[50000];

int count = 3;
int[] compact = new int[count];
Array.Copy(arr, compact, count);
arr = null;

Upvotes: 1

James
James

Reputation: 9985

I think this is equivalent to your list example

var x = new Double[50000000];
//Lots of memory used here
GC.Collect(2);
//Still lots of memory used
var y = new Double[3];
Array.Copy(x, 0, y, 0, 3);
x = y;
GC.Collect(2);
//Much less memory now used

Upvotes: 0

Spikeh
Spikeh

Reputation: 3695

I'm afraid not. Arrays, by their very nature, are fixed size.

http://msdn.microsoft.com/en-us/library/9b9dty7d.aspx

Specifically:

The number of dimensions and the length of each dimension are established when the array instance is created. These values can't be changed during the lifetime of the instance.

You will be able to free up memory by setting array elements to null, though. And of course, you can resize arrays manually, but that requires you to create another array and copy the relevant elements into it.

Upvotes: 1

Related Questions