c# - c# 中的简单批处理文件处理函数中可能存在内存泄漏
问题描述
我正在运行一个非常简单的函数,它从文本文件中批量读取行。每行包含一个 sql 查询,因此该函数获取指定数量的查询,针对 SQL 数据库执行它们,然后获取下一批查询,直到读取整个文件。问题是随着时间的推移,文件非常大,该过程开始显着减慢。我猜函数中某处存在内存泄漏,但无法确定它可能在哪里。此功能运行时没有其他任何事情发生。我的编程技能充其量是粗略的,所以请放轻松。:)
for (int x = 0; x<= totalBatchesInt; x++)
{
var lines = System.IO.File.ReadLines(file).Skip(skipCount).Take(batchSize).ToArray();
string test = string.Join("\n", lines);
SqlCommand cmd = new SqlCommand(test.ToString());
try
{
var rowsEffected = qm.ExecuteNonQuery(CommandType.Text, cmd.CommandText, 6000, true);
totalRowsEffected = totalRowsEffected + rowsEffected;
globalRecordCounter = globalRecordCounter + rowsEffected;
fileRecordCounter = fileRecordCounter + rowsEffected;
skipCount = skipCount + batchSize;
TraceSource.TraceEvent(TraceEventType.Information, (int)ProcessEvents.Starting, "Rows
progress for " + folderName + "_" + fileName + " : " + fileRecordCounter.ToString() + "
of " + linesCount + " records");
}
catch (Exception esql)
{
TraceSource.TraceEvent(TraceEventType.Information, (int)ProcessEvents.Cancelling, "Error
processing file " + folderName + "_" + fileName + " : " + esql.Message.ToString() + ".
Aborting file read");
}
}
解决方案
您的代码有很多问题:
你永远不会处置你的命令。这是 ODBC 驱动程序的本机句柄,等待垃圾收集器处理它是非常糟糕的做法。
无论如何,您不应该单独发送这些命令。要么在一个命令中一次性发送它们,要么使用事务将它们组合在一起。
这就是它随着时间变慢的原因:
File.ReadLines(file).Skip(skipCount).Take(batchSize)
将一遍又一遍地读取同一个文件并忽略每次尝试越来越多的行,因此随着被忽略(但已处理)的行数越来越大而越来越慢.
要修复 #3,只需创建一次枚举器并分批迭代它。在纯 C# 中,您可以执行以下操作:
using var enumerator = File.ReadLines(file).GetEnumerator();
for (int x = 0; x<= totalBatchesInt; x++)
{
var lines = new List<string>();
while(enumerator.MoveNext() && lines.Count < batchSize)
list.Add(enumerator.Current);
string test = string.Join("\n", lines);
// your code...
}
或者,如果您使用的是 Morelinq(我推荐),则如下所示:
foreach(var lines in File.ReadLines(file).Batch(batchSize))
{
// your code...
}
推荐阅读
- math - python AttributeError:模块'math'没有属性'comb'
- bash - 遍历 bash 上的 txt 文件中的列表
- javascript - 为什么一个大的正数小于0?
- laravel - 使用数据透视表过滤数据 Laravel Eloquent
- total.js - 通过 RestBulider 发送和接收文件
- python - 如何选择和索引每组 Pandas 数据帧中的最大值?
- python - 在python中计算列表的总和
- sql - 平均值超过阈值的持久性
- azure - 启用自动缩放后,Aks 未与 keyvault 连接。我们使用 aks 池身份来连接 Keyvault
- c# - 如何创建一个全局变量来保存具有通用抽象类的实例?或者它甚至是正确的事情?