我正在使用 EF6,并试图了解实际发生的情况以及对 EF 的异步调用在紧密循环中运行数千次的性能影响。 也就是说,这个循环:
using (var db = dbContext()) {
vary query = db.MyTable.Where(...);
cnt = 10000;
for (var i = 0; i < cnt; i++)
await query.ToListAsync();
}
我的想法是,在"using"语句结束时,所有 10000 个将按顺序处理。
将其与同步调用进行比较时(只是查询。ToList(( without await(,将发生完全相同的事情,并且性能应该是相同的。 我的结果显示跑步时间相差 1.5 倍。
问题:为什么时间不同,我上面的假设是否正确?
我的想法是,在"使用"语句的末尾,所有 10000 将按顺序处理。
不,每次等待时都会处理它们...ToListAsync(( 被调用。
问题:为什么时间不同,我的假设是上面的吗 正确?
因为在这种情况下使用异步会产生开销,因此会降低性能...ToListAsync((,因为您正在尝试最大化单线程吞吐量。
如果您进行一些添加,这将起作用,例如。但是您需要提前了解cnt
。
cosnt int cnt = 10000;
const int pageSize = 1000;
int pageNumber = 0;
var list = new List<MyTableRecord>();
using (var db = dbContext())
{
for (var i = 0; i < cnt ; i++)
{
vary query = db.MyTable.Where(...).Skip(pageNumber++ * pageSize).Take(pageSize);
list.AddRange(await query.ToArrayAsync());
}
}
请注意,如果您尝试将 1000 * 10000 条记录加载到计算机中,list
可能会炸毁计算机的内存(OutOfMemoryException
(。
更现实的解决方案:
using (var db = dbContext())
{
IEnumerable<MyTableRecord> rows;
while ((rows = db.MyTable.Where(...).Skip(pageNumber++ * pageSize).Take(pageSize)).Any())
{
list.AddRange(rows);
}
}
请注意,您可能会在同一连接内运行所有查询,这可能会导致其超时。