【发布时间】:2019-10-17 12:13:43
【问题描述】:
我对 IEnumerable 内存使用问题感到困惑,尤其是比较来自 DB 的 IEnumerable 数据源和来自代码 yield return const 值的 IEnumerable 数据源。
我有一个Memory 函数来检查内存使用情况。
static string Memory()
{
return (Process.GetCurrentProcess().WorkingSet64 / (1024 *
1024)).ToString();
}
- 所以这里我使用的是EF CORE 3.0,一共访问了150000条记录的表
using DataContext context = new DataContext();
Console.WriteLine(Memory()); //21
IEnumerable<User> users = context.Users;
foreach (var i in users) {}
Console.WriteLine(Memory());//101
Console.WriteLine(GC.GetTotalMemory(true));//46620032
由于某种原因我无法上传图片,所以我需要输入结果,对此感到抱歉。(结果在代码中为 cmets)。
- 下一个示例是使用
yield return生成 IEnumerable 数据。
static IEnumerable<User> Generator(int max)
{
for (int i = 0; i < max; i++)
{
yield return new User { Id = 1, Name = "test" };
}
}
这是结果
Console.WriteLine(Memory());// 21
IEnumerable<User> users = Generator(150000);
foreach (var i in users){}
Console.WriteLine(Memory());// 24
Console.WriteLine(GC.GetTotalMemory(true)); // 658040
现在,我对示例 1 和示例 2 感到非常困惑。我的理解是,对于 IEnumerable 数据源,它会一次读取一个,而不是整个集合,因此它可以减少内存使用量,就像示例 2. 但是,在使用 EF CORE 时(我知道这不是 EF CORE 特有的,但我需要一个具体的例子。),我认为它仍然是一一拉,但我的问题是它为什么使用比第二个例子更多的内存。那么它是不是一个一个地拉着每一个记录呢?最后,我将数据库中的所有记录都保存在内存中,对吗?但是为什么第二个使用这么少的内存呢?我正在产生相同的记录。如果有人可以解释这一点,我们将不胜感激。谢谢!!!
【问题讨论】:
-
EF Core 不会一一拉取记录,实际上它返回的是
IQueryable而不是IEnumerable -
@VidmantasBlazevicius 当我迭代集合时它必须是
IEnumerable不能是IQueryable。由于iqueryable和ienumerable都被延迟执行,因此它正在一一拉动。 -
IQueryableextendsIEnumerable,所以你在IEnumerable上做的任何事情你也可以在IQueryable上做。
标签: c# .net entity-framework .net-core entity-framework-core