如何释放内存?

发布于 2024-09-30 18:02:14 字数 710 浏览 9 评论 0原文

我有以下方法来循环遍历表,更改每行中的一些值并将更改保存回数据库。为了让事情进展得更快,我以 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

墟烟 2024-10-07 18:02:14

存储库保存对其正在跟踪的每个实体的引用,因此当存储库处于活动状态并跟踪它时,您将无法处置实体。这意味着您要么需要处置存储库,要么在完成处理后分离每个实体。

选项 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

黒涩兲箜 2024-10-07 18:02:14

也许你可以尝试这个:(我没有测试过)

db.SaveChanges()
For Each record In records
    record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing

maybe you can try this: (I didn't test it)

db.SaveChanges()
For Each record In records
    record.dispose ''only if class table got a dispose method
Next
records.clear
records = Nothing
錯遇了你 2024-10-07 18:02:14

我绝不是 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.

关于从前 2024-10-07 18:02:14

如果您不需要更新实体,请使用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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文