实体框架内存使用量

5
实体框架在向数据库插入新对象时似乎会使用过多的内存。
for(int i = 0; i < numOwners; ++i)
{
    var owner = Owner.CreateOwner();
    db.AddToOwnerSet(owner);
    for(int j = 0; j < numChildren; ++j)
    {
        var child = Child.CreateChild();
        owner.Childs.Add(child);
    }
}
db.SaveChanges();

在这个阶段,这些对象包含非常少的数据元素。将这140,000个对象插入到数据库中时,应用程序的总内存使用量为600 MB,而300,000个对象的内存使用量为1.2 GB。这些对象很小,只有一个字符串名称和一个整数键。
我可以通过将SaveChanges调用放入循环中来减少内存使用量,但是执行时间会变得更差,而且已经相当糟糕了。
有人知道为什么实体框架使用如此多的内存,或者如何减少内存使用量吗?
3个回答

2

我知道这是一个老问题,但今天我遇到了同样的问题,并成功找出了原因!

似乎生成SQL脚本导致内存大幅跳动。我发现创建存储过程并将它们链接到我的对象(但要确保按照此文章所示返回ids的值)可以节省超过300MB的内存。


2
由于实体框架(as do many ORM's)在内存中保存数据,所以像许多内存集合一样,可能有内部数组。当您将项目添加到集合中时,内部数组的容量会加倍。
例如,如果您有一个包含256个项的ArrayList集合,并将第257个项添加到其中,则在内部会分配一个新的内存块用于512个项的数组,将256个项的数组复制到新的512个项的数组中,然后使256个项的数组可供垃圾回收。因此,在转换点上,您将在内存中分配768个项目,只是因为添加了第257个项目。我在使用MemoryStream时遇到过这个问题,因为您需要几乎比实际需要的连续未碎片的内存多3倍。这就是您在集合上看到的.Capacity属性,它几乎总是2的幂(因为它根据需要加倍)。
我敢打赌,有一些内部数组会随着需要而加倍,以支持您在内存中对象的集合。因此,相同类型的30万个对象可能会保存在大小为524288的内部数组中。此外,如果它类似于.NET Framework中其他地方的类似技术,那么当添加第262145个项目时,同时存在262144和524288的数组,而项目被复制到新数组中。总共有786432个项目在内存中。旧数组将一直保留,直到垃圾回收器决定不再需要它。
在实体框架中可能有一些关于并发支持的选项,您可以禁用这些选项以改善内存使用情况。我只是在这里推测,但是为了支持并发,他们在内存中存储当前版本的数据和其原始版本以进行比较。
我还会查看与您交互的数据的过滤方式。尝试找到聪明的标准来限制查询和加载到内存中的内容。例如,如果您有一个允许用户编辑客户帐户的应用程序,但只分配给他们某些帐户,则将其用作过滤标准,以便仅在内存中加载那些用户可能与之交互的帐户。

1

你的对象在实际数据方面可能是“小”的,但每个对象并不是DTO——实体框架为每个实体附加了大量样板代码,这意味着每个对象的实际大小相当大。

如果你在持续地处理大型对象图,则考虑使用类似NHibernate的东西,它是稳定的、成熟的并被证明可以工作。实体框架在功能和性能方面非常落后。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接