M
Mr. Mountain
I have a need to implement a linked list that will hold a large number of
items. I have done a little performance testing to compare the linked list
against the framework's standard hashtable.
So far the linked list meets my objectives in all ways -- except for one
problem that it exhibits. It has a garbage collection problem.
If I insert 4 million test objects into a hashtable and run tests
repeatedly, the garbage collector does its job as one would expect. I can
run as many repeated tests as I wish.
When I do the exact same test with the same 4 million test objects in the
linked list, the first test is fine. The next test results in an
out-of-memory exception because the garbage collector does not run. If I
call gc.collect between tests, there are no out-of-memory problems for the
linked list.
Why is it necessary to call gc.collect manually when the linked list is
used? I have never had to request a manual garbage collection in any other
situation.
What steps can I take to optimize the memory management when a large linked
list needs to be used? This is NOT a matter of roots pointing to objects.
The objects are all free to be collected after each test completes.
I'm really interested in knowing if the framework can perform collection as
efficiently (and automatically) for several million individually allocated
list nodes as it can for the contiguous memory block that underlies a
hashtable. If it can, what technique(s) do I need to use to make it happen?
My test code looks like this (I show the hashtable example, but the linked
list test driver is exactly the same):
private void btnTest_Click(object sender, System.EventArgs e)
{
DateTime start = DateTime.Now;
Hashtable ht = new Hashtable();
for (int i = startIndex; i < testSize; i++)
{
Hashtable innerHt = new Hashtable();
ht.Add(i, innerHt);
for (int j = startIndex; j < testSize; j++)
{
OrganizationMember om = new
OrganizationMember(j.ToString(), j.ToString(), "Test");
innerHt.Add(j, om);
}
}
for (int i = startIndex; i < testSize; i++)
{
Hashtable innerHt = ht as Hashtable;
for (int j = startIndex; j < testSize; j++)
{
OrganizationMember om = innerHt[j] as OrganizationMember;
}
}
lblSystemResults.Text = (DateTime.Now -
start).TotalMilliseconds.ToString();
}
private void btnClear_Click(object sender, System.EventArgs e)
{
System.GC.Collect();
}//btnClear_Click
items. I have done a little performance testing to compare the linked list
against the framework's standard hashtable.
So far the linked list meets my objectives in all ways -- except for one
problem that it exhibits. It has a garbage collection problem.
If I insert 4 million test objects into a hashtable and run tests
repeatedly, the garbage collector does its job as one would expect. I can
run as many repeated tests as I wish.
When I do the exact same test with the same 4 million test objects in the
linked list, the first test is fine. The next test results in an
out-of-memory exception because the garbage collector does not run. If I
call gc.collect between tests, there are no out-of-memory problems for the
linked list.
Why is it necessary to call gc.collect manually when the linked list is
used? I have never had to request a manual garbage collection in any other
situation.
What steps can I take to optimize the memory management when a large linked
list needs to be used? This is NOT a matter of roots pointing to objects.
The objects are all free to be collected after each test completes.
I'm really interested in knowing if the framework can perform collection as
efficiently (and automatically) for several million individually allocated
list nodes as it can for the contiguous memory block that underlies a
hashtable. If it can, what technique(s) do I need to use to make it happen?
My test code looks like this (I show the hashtable example, but the linked
list test driver is exactly the same):
private void btnTest_Click(object sender, System.EventArgs e)
{
DateTime start = DateTime.Now;
Hashtable ht = new Hashtable();
for (int i = startIndex; i < testSize; i++)
{
Hashtable innerHt = new Hashtable();
ht.Add(i, innerHt);
for (int j = startIndex; j < testSize; j++)
{
OrganizationMember om = new
OrganizationMember(j.ToString(), j.ToString(), "Test");
innerHt.Add(j, om);
}
}
for (int i = startIndex; i < testSize; i++)
{
Hashtable innerHt = ht as Hashtable;
for (int j = startIndex; j < testSize; j++)
{
OrganizationMember om = innerHt[j] as OrganizationMember;
}
}
lblSystemResults.Text = (DateTime.Now -
start).TotalMilliseconds.ToString();
}
private void btnClear_Click(object sender, System.EventArgs e)
{
System.GC.Collect();
}//btnClear_Click