kind of memory leak in dataset/dataadapter update?

H

Helge C. Rutz

Hi,

we had strange memory usage / memory leak of our web application which we
could strip down to a (at least for us) unexpected behaviour of a dataset.

Scenario: With application start we open a dataset keeping a reference of
some datatables as long as the app runs. During this time we do regular
updates of these tables by changing the dataset and then passing it to the
dataadapter for update.
During update the dataadapter seems to build some help tables and/or
structures which are held as long as the dataset exists. Because this is
done for every update again and again, the allocated memory sums up to an
unacceptable amount.
Our first workaround is to regularly copy the dataset to free the old
dataset with all related memory.

Is this a known behaviour/bug?
We use framework 1.1. Is this maybe fixed with SP1?
Are there other workarounds for this?

best regards
Helge
 
W

W.G. Ryan eMVP

Helge - without seeing the code it's hard to tell. My guess is that new
tables or data is being copied/ references held on to - but not necessarily
as somethign that the adapter or datatable are doing.
 
H

Helge C. Rutz

W.G. Ryan eMVP said:
Helge - without seeing the code it's hard to tell. My guess is that new
tables or data is being copied/ references held on to - but not
necessarily
as somethign that the adapter or datatable are doing.

we tried several ways to find the memory leak and at last we were able to
identify the dataset allocating more and more memory using the CLR Profiler.
What I can say is, that the dataset memory grows with each update.
We tried to reproduce this with a simple saple app, but wasn't able to do
so.
The actual code is our own datalayer for our product, and to complex to
post.
We will try to get a sample with an even complex dataset with multiple
references/relations to reproduce this, but this will take some time because
tha actual focus is to keep it running.

In the moment we just copy the dataset to itself to free the extra memory

this.mydataset = this.mydataset.copy

Bye
Helge
 
H

Helge C. Rutz

Hi everybody,

we were able to exactly localize the problem in the datatable.
Each time we check the datatables for changes with Select, there is an
internal index build.
These indexes are later deleted when you pass the datatable to the
dataadapter.
But in our code we have a lot of tables in the dataset where we check all
for changes and only update the ones with changes.
When the changes only occur in the same tables for a long time, the other
tables get more and more indexes consuming a lot of memory.

The following piece of code demonstrate this behaviour.
It generates more than 400Meg on my machine, and it's the Select method
doing this!
Only a call of the AcceptChanges method clears the memory.
If your machine doesn't have that much memory, be careful!
We have not examined the problem on .NET SP1, perhaps it is fixed.

For me, creating a static index without reusing it anytime looks like a bug.
Any comments on that?

Helge

----------------------------------------------------
class Class1
{
[STAThread]
static void Main(string[] args)
{
// build a very simple DataSet
System.Data.DataSet ds = new DataSet();
System.Data.DataTable table = ds.Tables.Add("Table");
table.Columns.Add(new System.Data.DataColumn("ID", typeof(Guid)));

// add some Data to your one table to make the effect more dramatic ;-)
for (int i = 0; i< 10000; ++i)
{
System.Data.DataRow row = table.NewRow();
row["ID"] = Guid.NewGuid();
table.Rows.Add(row);
}
table.AcceptChanges();

// dump memory before
Class1.DumpMemory();

for(int i = 0; i <10000; ++i)
{
// this simple select (doing nothing) executed 10000 times generates over
400Meg of memory!
// And you don't get rid of it with GC.Collect()!
table.Select(null,null,DataViewRowState.ModifiedCurrent);
}
// dump memory after! Suprise!
Class1.DumpMemory();

// only if you call AcceptChanges the memory is cleared!
ds.AcceptChanges();

Class1.DumpMemory();
}

static void DumpMemory()
{
System.GC.Collect();
System.Console.WriteLine("TotalMemory: " +
GC.GetTotalMemory(true).ToString());
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top