dr.*_*vil 7 .net c# memory-leaks out-of-memory large-object-heap
我有一个.NET 3.5应用程序
当我对应用程序进行概要分析时,我可以确认这些字符串存储在LOH中,但稍后它们也会被GC回收,因此在给定时间内,只有最多10个字符串在LOH中(10个线程正在运行).
我的理解是,这些大字符串位于LOH,然后由GC回收,但不知何故由于它们的分配位置(并且在LOH中因此没有被压缩)这导致碎片化.尽管操作中没有内存泄漏,但仍会发生这种情况.
它不会导致~100K次出现问题,但是当它达到1M +时会出现内存异常.
我正在使用ANTS Memory Profiler,这是我在早期执行中得到的结果:
.NET Using 70MB of 210MB total private bytes allocated in to the application
Number of Fragments: 59
Number of Large Fragments : 48 (99.6% of free memory)
Largest Fragment: 9MB
Free Space: 52% of total memory (37MB)
Unmanaged Memory: 66% of total private memory (160MB)
Run Code Online (Sandbox Code Playgroud)
是的。听起来是对的。LOH 变得碎片化,这导致运行时无法为大字符串分配足够的连续空间。
你有几个选择,我想你应该选择最简单有效的一个。这完全取决于它是如何写的。
将您的琴弦分成足够小的块,使其不在 LOH 中。(小于 85K - 注意:将对象放入 LOH 的逻辑并不是那么简单。)这将使 GC 能够回收空间。这决不能保证修复碎片——否则肯定仍然会发生。如果你把琴弦变小,但最终还是在 LOH 上——你就会推迟解决这个问题。这取决于您需要处理的字符串超过 100 万个。另一个缺点是 - 您仍然需要将字符串加载到内存中来分割它,所以无论如何它最终都会出现在 LOH 上。在应用程序加载字符串之前,您应该先缩小字符串。有点像第22条军规。编辑:加布在评论中指出,如果您可以将字符串加载到StringBuilder第一个中,那么在幕后,它会尽力将事情排除在 LOH 之外(直到您调用ToString它)。
将字符串的处理分解为一个单独的过程。使用进程而不是线程。使用每个进程处理 10K 字符串,然后终止该进程并启动另一个进程。这样,每个流程都会从头开始。这样做的优点是它不会改变您的字符串处理逻辑(以防您无法缩小字符串以进行处理),并且避免了 #1 中的 catch-22。缺点是这可能需要对应用程序进行更大的更改,并协调主进程和从处理进程之间的工作。诀窍是master只能告诉它大字符串在哪里,它不能直接把它给它,否则你又回到了catch-22。
| 归档时间: |
|
| 查看次数: |
2235 次 |
| 最近记录: |