我正在调查一些代码(由其他人编写)以查找导致内存使用量快速增加到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];
}
我已经看到了与垃圾收集器无法跟上的内存相关问题的一些答案。在我看来,在每次迭代中创建一个新对象是不必要的。
答案 0 :(得分:4)
这取决于可用的内存量。由于你的循环体的最后一行覆盖lin
,所以似乎没有人对它进行引用。只有嫌疑人才会rdr
和conn
,因为他们可能会毫无理由地保留一个嫌疑人。如果他们不这样做,它将可用于垃圾收集,它将负责释放你在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天免费试用,因此您可以在购买前弄清楚它是否会对您有所帮助。