Tony Hinkle
Tony Hinkle

Reputation: 4742

Could this code cause excessive memory usage?

I am investigating some code (written by someone else) to find what is causing memory usage to quickly increase to 8 GB. I'm not a true developer, more of a self-taught hobbyist that does some coding at work, so this is a bit over my head.

Could the following code, particularly creating a new object for lin on every iteration, cause memory to grow quickly? There are about 3 million records being processed. The data in each column is nothing extraordinary.

conn is a custom class.

SqlDataReader rdr = comm.ExecuteReader();
object[] lin = new object[17];

while (rdr.Read()){

    rdr.GetValues(lin);
    conn.Submit(lin, ref cmdString, ref recCount);
    lin = new object[17];

    }

I've seen some answers to memory-related questions about the garbage collector not being able to keep up. It seems to me that creating a new object in each iteration is unnecessary.

Upvotes: 3

Views: 128

Answers (3)

Martin Noreke
Martin Noreke

Reputation: 4136

Going into further detail in what Oppassum said, I think that your "lin" variable may be the culprit.

By performing the new operation on lin every loop, you are allocating that memory and not reusing it. You are correct to create the object outside of the loop, as this reuses the object memory. I can't remember if rdr.GetValues() requires that the object array you pass in is empty or not. It may just overwrite existing values, so clearing becomes unnecessary.

SqlDataReader rdr = comm.ExecuteReader();
object[] lin = new object[17];

while (rdr.Read())
{
    rdr.GetValues(lin);
    conn.Submit(lin, ref cmdString, ref recCount);

    // Clearing, but may not be nessessary.
    for(int i; i<lin.Length;i++)
        lin[i] = null;
}

With all of that said, the best way to figure out memory issues is still going to be using a profiler such as the one from RedGate. It comes with a 14 day free trial so you can figure out if it will help you before buying it.

Upvotes: 0

nozzleman
nozzleman

Reputation: 9649

It depends on how much Memory is available. Since the last Line of your loops body overwrites lin, no one seems hold a reference to it anymore. Only suspects would be rdr and conn, since they might keep one for no obvious reason. If they do not, it will get available for garbage collection which will take care of releasing the resources of the arrays you initialized when it is nessecary.

However, a cleaner solution could look like this, where the array gets cleared and reused instead of initializing a new one and overriding the old variable which used to hold the previous one.

var lin = new object[17];

while (rdr.Read()){
    rdr.GetValues(lin);
    conn.Submit(lin, ref cmdString, ref recCount);
    Array.Clear(lin, 0, 17);
}

Atlernatively, you could move the array-declaration into inner scope like i said in my comment:

while (rdr.Read()){
    var lin = new object[17];
    rdr.GetValues(lin);
    conn.Submit(lin, ref cmdString, ref recCount);
}

Im not sure on which of those solutions would be faster, but im sure you can figure it out by trial and error.

Upvotes: 4

oppassum
oppassum

Reputation: 1765

You should not have to create a new object each time the loop goes through. rdr.GetValues(lin) will overwrite the values in the memory, assuming it fills in all 17 spaces.

If it doesn't clear the spaces, you'll want to at the very least clear the 17 spaces to make sure you aren't re-using old data.

Upvotes: 1

Related Questions