实体数据查询和内存泄漏 [英] Entity data querying and memory leak

查看:140
本文介绍了实体数据查询和内存泄漏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我下载了大量的数据在一个循环,但一些操作后,我删除他们,但我所看到的是,内存分配增长非常快,几秒钟和1GB,所以每次迭代后如何清洁?

 使用(VAR CONTEX =新DB)
{

VAR输入= CONTEX。 AIMRInputs.Where(X => x.Input_Type == 1);

的foreach(在输入VAR输入)
{
VAR数据= contex.Values.Where(X => x.InputID == input.InputID).OrderBy(X => x.TimeStamp).ToList();

如果(data.Count == 0)继续;
的foreach(数据VAR值)
{
Console.WriteLine(Value.property);
}
data.Clear();


}
}


解决方案

您可以做的,是无法改变的跟踪,因为你没有在你的代码更改任何数据的第一件事。这可以防止加载的对象获得附加到上下文:



有关的DbContext (EF> = 4.1):

  VAR输入= contex.AIMRInputs.AsNoTracking()
。凡(X => x.Input_Type == 1 );

  VAR数据= contex.Values.AsNoTracking()
。凡(X => x.InputID == input.InputID)
.OrderBy(X => x.TimeStamp)
.ToList();

修改



有关EF 4.0,你可以留下您的疑问,因为他们不过是添加以下为在使用块中的前两行:

  contex.AIMRInputs.MergeOption = MergeOption.NoTracking; 
contex.Values.MergeOption = MergeOption.NoTracking;

这禁用变化为的ObjectContext 跟踪



编辑2



...尤其指的是低于@詹姆斯雷亚特吉的评论 AsNoTracking 减少内存占用:



这往往是真实的(如在这一问题的模型/查询),但不总是!实际使用 AsNoTracking 可以对内存的使用会适得其反。



这是什么 AsNoTracking 做的时候对象在内存中得到具体化




  • 第一:它没有实体连接到环境和因此,不会产生在上下文的状态管理器条目。这些条目消耗内存。当使用波苏斯条目含有被首次加载时它/附加到上下文的实体的属性值的快照 - 除了对象本身基本上所有(标量)的复制性能。所以comsumed内存占用(大约)的两倍对象的大小时, AsNoTracking 将不适用。


  • 第二:在另一方面,当实体没有得到附加到上下文EF不能利用密钥值和对象引用身份之间身份映射的优点。这意味着,相同的密钥对象将被物化多次这comsumes更多的内存,而无需使用 AsNoTracking EF将确保一个实体只有每个键值兑现一次。




相关实体被加载时,第二点显得尤为重要。简单的例子:



我说,我们有一个订单客户实体和秩序有一个客户 Order.Customer 。说订单对象有大小为10字节和客户对象的大小20个字节。现在我们运行此查询:

  VAR orderList = context.Orders 
.INCLUDE(O => o.Customer )。取(3).ToList();

和假设所有3加载订单分配有相同的客户。因为我们没有禁用跟踪EF一定会实现:




  • 3的订单对象= 3×10 = 30字节

  • 1的客户对象= 1X20 = 20字节(因为上下文识别客户是所有3个数量同样它物化,只有一个客户对象)

  • 3阶快照与原始值项与原始值= 1X20 = 20字节= 3×10 = 30字节

  • 1的客户快照条目



和:(为了简单起见假设我用复制的属性值的上下文条目具有的大小与实体本身相同)100字节





现在我们在禁用更改跟踪查询:

  VAR orderList = context.Orders。 AsNoTracking()
.INCLUDE(O => o.Customer)。取(3).ToList();



物化数据是:




  • 3的订单对象= 3×10 = 30字节

  • 3(!)的客户对象= 3×20 = 60字节(无身份映射每个键=多个对象,所有这三个客户对象将具有相同的属性值,但他们仍然在内存中的三个对象)

  • 无快照项



总:90字节



因此,使用 AsNoTracking 查询占用10个字节的内存较少的这种情况下。



现在,同样的计算以5目(取(5)),再次所有订单都有相同的客户:



没有 AsNoTracking




  • 5订单对象= 5×10 = 50字节

  • 1的客户对象= 1X20 = 20字节

  • 5与原始值= 5×10 = 50字节

  • 与原始值= 1X20 = 20字节1客户快照条目


为了快照条目

总:140字节



通过 AsNoTracking




  • 5订单对象= 5×10 = 50字节

  • 5(!)的客户对象= 5X20 = 100字节

  • 无快照项



总:150字节



这个时候使用 AsNoTracking 是10个字节更昂贵。



上面的数字是非常粗糙,但地方是一个盈亏平衡点在哪里使用 AsNoTracking 可需要更多的内存。



在内存中的差异使用间消费 AsNoTracking 或不强烈依赖于该查询,在模型中的关系和由该查询加载的具体数据。例如: AsNoTracking 将始终在内存消耗更好时,在上述所有(或大部分)的例子订单有不同的客户



结论: AsNoTracking 最基本的功能是作为一种工具来提高查询的性能的,而不是内存使用情况。在许多情况下,它也将消耗更少的存储器。但是,如果一个特定的查询需要与 AsNoTracking 更多的内存,请不要感到惊讶。最后,你必须衡量,取而代之的是固态决定或对 AsNoTracking 的内存占用。


I am downloading a lot of data in a loop but after some operations I remove them but what I see is that memory allocation is growing really fast, few seconds and 1GB, so how can clean after each iteration?

    using (var contex = new DB)
    {

        var inputs = contex.AIMRInputs.Where(x => x.Input_Type == 1);

        foreach (var input in inputs)
        {
            var data = contex.Values.Where(x => x.InputID == input.InputID).OrderBy(x => x.TimeStamp).ToList();

            if (data.Count == 0) continue;
            foreach (var value in data)
            {
               Console.WriteLine(Value.property);
            }
            data.Clear();


        }
    }

解决方案

The first thing you can do, is disabling change tracking because you are not changing any data in your code. This prevents that the loaded objects get attached to the context:

For DbContext (EF >= 4.1):

var inputs = contex.AIMRInputs.AsNoTracking()
    .Where(x => x.Input_Type == 1);

And:

var data = contex.Values.AsNoTracking()
    .Where(x => x.InputID == input.InputID)
    .OrderBy(x => x.TimeStamp)
    .ToList();

Edit

For EF 4.0 you can leave your queries as they are but add the following as the first two lines in the using block:

contex.AIMRInputs.MergeOption = MergeOption.NoTracking;
contex.Values.MergeOption = MergeOption.NoTracking;

This disables change tracking for ObjectContext.

Edit 2

...especially refering to @James Reategui's comment below that AsNoTracking reduces memory footprint:

This is often true (like in the model/query of this question) but not always! Actually using AsNoTracking can be counterproductive regarding memory usage.

What does AsNoTracking do when objects get materialized in memory?

  • First: It doesn't attach the entity to the context and therefore doesn't create entries in the context's state manager. Those entries consume memory. When using POCOs the entries contain a snapshot of the entity's property values when it was first loaded/attached to the context - basically a copy of all (scalar) properties in addition to the object itself. So the comsumed memory takes (roughly) twice as much as the object's size when AsNoTracking is not applied.

  • Second: On the other hand, when entities don't get attached to the context EF cannot leverage the advantage of identity mapping between key values and object reference identities. This means that objects with the same key will be materialized multiple times which comsumes additional memory while without using AsNoTracking EF will ensure that an entity is only materialized once per key value.

The second point becomes especially important when related entities are loaded. Simple example:

Say, we have an Order and a Customer entity and an order has one customer Order.Customer. Say the Order object has the size 10 byte and the Customer object the size 20 byte. Now we run this query:

var orderList = context.Orders
    .Include(o => o.Customer).Take(3).ToList();

And suppose all 3 loaded orders have the same customer assigned. Because we didn't disable tracking EF will materialize:

  • 3 orders objects = 3x10 = 30 byte
  • 1 customer object = 1x20 = 20 byte (because the context recognizes that the customer is the same for all 3 orders it materializes only one customer object)
  • 3 order snapshot entries with original values = 3x10 = 30 byte
  • 1 customer snapshot entry with original values = 1x20 = 20 byte

Sum: 100 byte

(For simplicity I assume that the context entries with the copied property values have the same size as the entities themselves.)

Now we run the query with disabled change tracking:

var orderList = context.Orders.AsNoTracking()
    .Include(o => o.Customer).Take(3).ToList();

The materialized data are:

  • 3 orders objects = 3x10 = 30 byte
  • 3 (!) customer objects = 3x20 = 60 byte (No identity mapping = multiple objects per key, all three customer objects will have the same property values, but they are still three objects in memory)
  • No snapshot entries

Sum: 90 byte

So, using AsNoTracking the query consumed 10 byte less memory in this case.

Now, the same calculation with 5 orders (Take(5)), again all orders have the same customer:

Without AsNoTracking:

  • 5 orders objects = 5x10 = 50 byte
  • 1 customer object = 1x20 = 20 byte
  • 5 order snapshot entries with original values = 5x10 = 50 byte
  • 1 customer snapshot entry with original values = 1x20 = 20 byte

Sum: 140 byte

With AsNoTracking:

  • 5 orders objects = 5x10 = 50 byte
  • 5 (!) customer objects = 5x20 = 100 byte
  • No snapshot entries

Sum: 150 byte

This time using AsNoTracking was 10 bytes more expensive.

The numbers above are very rough, but somewhere is a break-even point where using AsNoTracking can need more memory.

The difference in memory consumption between using AsNoTracking or not strongly depends on the query, the relationships in the model and the concrete data that are loaded by the query. For example: AsNoTracking would be always better in memory consumption when the orders in the example above all (or mostly) have different customers.

Conclusion: AsNoTracking is primarily meant as a tool to improve query performance, not memory usage. In many cases it will also consume less memory. But don't be surprised if a specific query needs more memory with AsNoTracking. In the end you must measure the memory footprint for a solid decision in favor or against AsNoTracking.

这篇关于实体数据查询和内存泄漏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆