简体   繁体   中英

Memory leaks while using array of double

I have a part of code that operates on large arrays of double (containing about 6000 elements at least) and executes several hundred times (usually 800) .

When I use standard loop, like that:

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
}

The memory usage rises for about 40MB (from 40MB at the beggining of the loop, to the 80MB at the end).

When I force to use the garbage collector to execute at every iteration, the memory usage stays at the level of 40MB (the rise is unsignificant).

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
singleRow = someObject.producesOutput();
//...
// do something with singleRow
// ...
GC.Collect()
}

But the execution time is 3 times longer! (it is crucial)

How can I force the C# to use the same area of memory instead of allocating new ones? Note: I have the access to the code of someObject class, so if it would be needed, I can change it.

Why are you allocating a large, empty singleRow only to overwrite it? Maybe you should be passing the array in to have its values modified in place. This would allow you to reuse it.

double[] singleRow = new double[6000];
int maxI = 800;
for(int i=0; i<maxI; i++)
{
    someObject.FillWithOutput(singleRow);
    //...
    // do something with singleRow
    // ...
}

If the method sometimes fills less than 6000 elements, it could simply return the fill count. Alternately, you could use a List<double> , which will allow resizing.

Make singleRow a parameter and pass it in to the call to producesOutput every time...

Basically your producesOutput method is probably allocating a new array every time, and the re-assignment of singleRow just marks the old memory as available to remove, but doesn't run the GC for performance reasons.

You aren't going to like this, but if you have to force GC you're doing something wrong. Keep in mind that memory may grow until there's pressure to trigger a GC - this is a GOOD thing because it means GC doesn't run until it has to.

Here's a silly-sounding test, but it might shed some light on what is happening. Inside FillWithOutput() comment out most of its functionality. Then run your loop and measure memeory. Incrementally un-comment out pieces of it until you see a blip. Now your're getting closer to what is causing the 'leak'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM