如何释放内存?
我有以下方法来循环遍历表,更改每行中的一些值并将更改保存回数据库。为了让事情进展得更快,我以 10,000 行为一组来获取数据。这是一个包含超过 2500 万条记录的大表。
问题是我的应用程序似乎没有释放任何内存。我尝试将 records
变量重新声明为 nothing
或显式调用垃圾收集器,但内存仍保留在那里。 运行内置的 VS10 分析器,我可以看到罪魁祸首是 system.linq.enumerable.tolist()
方法,它占用了我超过 98% 的内存。调用 saveChanges
后如何释放该内存?
db = New databaseEntities
Dim size = 25000000
Dim stepSize = 10000
For i = 0 to size Step stepSize
Dim sql = (From A In db.table).OrderBy(Function(A) A.Column).Skip(i).Take(stepSize)
Dim records As New List(Of table)
records = sql.ToList
For Each record In records
'do some work
Next
db.SaveChanges()
records = Nothing
GC.Collect()
Next
I have the following method for looping through a table, changint some values in every row and saving the chages back to the database. To make things go faster I am fetching data in sets of 10,000 rows. This is a large table with over 25 million records in it.
The problem is that my application doesn't seems to be releasing any memory. I have tried redeclaring the records
variable to nothing
or explicitly caling the garbage collector but the memory stays there.
Runnning the built-in VS10 profiler I can see that the culprit is the system.linq.enumerable.tolist()
method which takes up over 98% of my memory. How do I release that memory after the call to saveChanges
?
db = New databaseEntities
Dim size = 25000000
Dim stepSize = 10000
For i = 0 to size Step stepSize
Dim sql = (From A In db.table).OrderBy(Function(A) A.Column).Skip(i).Take(stepSize)
Dim records As New List(Of table)
records = sql.ToList
For Each record In records
'do some work
Next
db.SaveChanges()
records = Nothing
GC.Collect()
Next
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
存储库保存对其正在跟踪的每个实体的引用,因此当存储库处于活动状态并跟踪它时,您将无法处置实体。这意味着您要么需要处置存储库,要么在完成处理后分离每个实体。
选项 1)如果“做一些工作”不影响您返回记录的顺序,您可以将 databaseEntities 的创建移到 For 循环内,并使用 using 块来声明它。这应该会导致每个实体块每次都在 for 循环中被释放
选项 2) 如果您的操作本质上是并行的,并且您对一个“表”实体所做的操作不依赖于任何其他实体,那么您可以调用db.SaveChanges 之后的databaseEntities.Detach(record),这将使垃圾收集器能够回收实体的空间。
看看你的代码,我怀疑可以使用其中任何一个
The repository holds a reference to each entity it is tracking, so you won't be able to dispose an entity whilst the repository is live and tracking it. That means you either need to dispose the repository, or detach each entity after you've finished processing it.
Option 1) if "do some work" doesn't affect the order you'd return records in, you could move the creation of databaseEntities inside the For loop, and declare it with a using block. That should cause each block of entities to be release each time round the for loop
Option 2) If your operation is essentially parallel, and what you do to one "table" entity doesn't have any dependencies on any other, then you could call databaseEntities.Detach(record) after db.SaveChanges, which will enable the garbage collector to reclaim the entity's space.
Looking at your code, I suspect either of thse could be used
也许你可以尝试这个:(我没有测试过)
maybe you can try this: (I didn't test it)
我绝不是 Linq to SQL 专家,但我的猜测是 DataContext 缓存您已读取的所有行,因此您必须清空缓存或丢失对 DataContext 的引用。
I am by no means a Linq to SQL expert, but my guess is that the DataContext caches all rows you have read so you must either empty the cache or lose you reference to the DataContext.
如果您不需要更新实体,请使用
MergeOption.NoTracking
。上下文将不再保留对实体的引用,也不会进行修复。If you don't need to update the entities, use
MergeOption.NoTracking
. The context will no longer keep a reference to the entity, nor will it do fixup.