在负载较重的Windows服务上,.NET中OutOfMemoryException的原因是什么?

问题描述 投票:1回答:1

我有一个正在做一些维护工作的Windows服务。最近我们添加了一个尝试使用Lucene预先计算某些搜索结果的作业,从那时起它开始抛出OutOfMemory(OOM)异常。

我从WinDbgSOS得到的一些细节:

0:034> !analyzeoom
Managed OOM occured after GC #176014 (Requested to allocate 2621440 bytes)
Reason: Low on memory during GC
Detail: SOH: Failed to reserve memory (16777216 bytes)

!dumpheap -stat命令结果(最后一个)

65fe4944    81900     34614564 System.Byte[]
65fe2938    76014     35904328 System.Int32[]
65f96064       74     39988372 System.Int64[]
65fdf9ac  3208118    150302932 System.String
00265090      363    247694656      Free
Total 9035539 objects

所以有空闲内存,但它会碎片化,所有部分都少于16 MB(默认分配段)。 Lucene Cache保存字节数组,整数和int64。由于使用排序的查询,缓存被激活。 Lucene缓存实现基于WeakReferenceHashMap,因此在内存不足的情况下应由垃圾收集器清理。

Heapstat命令

0:034> !heapstat
Heap             Gen0         Gen1         Gen2          LOH
Heap0         1643476      2689484    526084512    196389976

Free space:                                                 Percentage
Heap0              12           12    170262384     77432248SOH: 32% LOH: 39%

日志文件中的异常转储如下所示:

Quartz.Core.ErrorLogger - Job (DEFAULT.precalculate-similar-index threw an exception.
Quartz.SchedulerException: Job threw an unhandled exception. ---> System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
   at Lucene.Net.Search.FieldCacheImpl.LongCache.CreateValue(IndexReader reader, Entry entryKey) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 685
   at Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 240
   at Lucene.Net.Search.FieldCacheImpl.GetLongs(IndexReader reader, String field, LongParser parser) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 639
   at Lucene.Net.Search.FieldCacheImpl.LongCache.CreateValue(IndexReader reader, Entry entryKey) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 667
   at Lucene.Net.Search.FieldCacheImpl.Cache.Get(IndexReader reader, Entry key) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 240
   at Lucene.Net.Search.FieldCacheImpl.GetLongs(IndexReader reader, String field, LongParser parser) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldCacheImpl.cs:line 639
   at Lucene.Net.Search.FieldComparator.LongComparator.SetNextReader(IndexReader reader, Int32 docBase) in C:\Dev\Lucene.Net_2_9_2\src\Lucene.Net\Search\FieldComparator.cs:line 481

我知道的唯一想法是异常是由内存碎片引起的。不幸的是,没有回答为什么内存没有被压缩的问题。

我们没有固定任何对象,看起来Lucene也没有,虽然!gcroot命令返回一些objets以下结果:

DOMAIN(0025D260):HANDLE(Pinned):1f13ec:Root:  02393250(System.Object[]) - from !gcroot
ESP:16f2e4: sizeof(02393250) =    123436600 (   0x75b7e38) bytes (System.Object[]) - size of the pinned arrays of objects

系统:qazxsw pi R2 32位 总提交字节数:~950 MB 保留字节总数:~1,666 MB(数字取自性能监视器)

在完成短批次之后,索引搜索器以及相关的索引读取器将定期关闭。之后,计划新批次并继续工作。 OOM确实会在运行几个小时后出现。此异常被捕获,服务继续运行。

.net memory-leaks lucene.net out-of-memory
1个回答
1
投票

没有泄漏,但由于高CPU和内存负载,GC抛出了可捕获的System.OutOfMemoryException(OOM)异常。因此,从一方面来看,流程继续运作,而另一方面,索引没有更新。

至少我设法以某种方式降低了内存压力,现在系统运行正常。

正如Simon Svensson指出的那样,如果读者仍处于打开状态,GC不会收集,所以我决定检查代码如何处理读者。事实证明,索引开放的数量相对较多。在一个地方打开索引并将其作为参数发送,使问题消失。

© www.soinside.com 2019 - 2024. All rights reserved.