这段代码会导致过多的内存使用吗?

时间:2015-07-02 14:03:20

标签: c#

我正在调查一些代码(由其他人编写)以查找导致内存使用量快速增加到8 GB的内容。我不是一个真正的开发人员,更像是一个自学成才的爱好者,他在工作中做了一些编码,所以这有点过头了。

以下代码,特别是在每次迭代中为lin创建新对象,是否会导致内存快速增长?大约有300万条记录正在处理中。每栏中的数据都不是特别的。

conn是一个自定义类。

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];

    }

我已经看到了与垃圾收集器无法跟上的内存相关问题的一些答案。在我看来,在每次迭代中创建一个新对象是不必要的。

3 个答案:

答案 0 :(得分:4)

这取决于可用的内存量。由于你的循环体的最后一行覆盖lin,所以似乎没有人对它进行引用。只有嫌疑人才会rdrconn,因为他们可能会毫无理由地保留一个嫌疑人。如果他们不这样做,它将可用于垃圾收集,它将负责释放你在nessecary时初始化的数组的资源。

但是,一个更干净的解决方案看起来像这样,数组得到cleared并重新使用,而不是初始化一个新的并覆盖用于保存前一个的旧变量。

var lin = new object[17];

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

Atlernatively,你可以像我在评论中所说的那样将数组声明移动到内部范围中:

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

我不确定哪种解决方案会更快,但我相信你可以通过反复试验来解决这个问题。

答案 1 :(得分:1)

每次循环通过时,您不必创建新对象。 rdr.GetValues(lin)将覆盖内存中的值,假设它填充了所有17个空格。

如果它没有清除空格,您至少要清除17个空格,以确保您不会重复使用旧数据。

答案 2 :(得分:0)

进一步了解Oppassum所说的内容,我认为你的“lin”变量可能是罪魁祸首。

通过对每个循环执行新操作,您将分配该内存而不重用它。在循环外创建对象是正确的,因为这会重用对象内存。我不记得rdr.GetValues()是否要求传入的对象数组是空的。它可能只是覆盖现有值,因此不需要清除。

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;
}

总而言之,找出内存问题的最佳方法仍然是使用分析器,例如来自RedGate的分析器。它提供14天免费试用,因此您可以在购买前弄清楚它是否会对您有所帮助。