内存不足异常 - WCF服务

4
我有一个已发布的WCF(C#)项目,遇到了“OutOfMemoryException”问题。DLL是使用“Any CPU”构建的,AppPool内存设置为0(表示没有限制)。 我每分钟持续处理大约1500个请求和其他大约100个请求。该项目使用EntityFramework。应用程序中有缓存(它是一个字典)。
我进行了一些故障排除以尝试找出问题,但目前还不清楚。我尝试计算总内存使用量(通过调用“GC.GetTotalMemory(false)”)和缓存列表的大小。在获取OOM异常时,缓存大小约为7 MB(30 KB每个对象2500个),而总内存使用量在600 MB到1.5 GB之间变化。
因此,很明显内存并没有满,资源也会被GarbageCollector定期清除(内存大小并非一直增加)。因此,OOM异常不是因为内存已满。
主要看到日志中在将对象序列化为JSON(我使用Newtonsoft)或对字符串执行某些操作(连接,替换,Regexreplace等)时发生OOM异常,以下是一些异常示例:
System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.Text.StringBuilder.ExpandByABlock(Int32 minBlockCharCount)
at System.Text.StringBuilder.Append(Char* value, Int32 valueCount)
at System.Text.StringBuilder.Append(String value, Int32 startIndex, Int32 count)
at System.Text.RegularExpressions.RegexReplacement.Replace(Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
at System.Text.RegularExpressions.Regex.Replace(String input, String pattern, String replacement)

并且

System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown.
at System.String.ReplaceInternal(String oldValue, String newValue)
at System.String.Replace(String oldValue, String newValue)

有什么想法或建议可以用来复现问题吗?

验证进程的位数。您会发现它是32位的。 - usr
我该如何获取位数?DLL是使用“任何 CPU”设置构建的,服务器正在运行 Windows Server 2012 x64。因此,DLL 的正常行为是 64 位! - Mostafa
DLLs会采用托管进程的位数。使用Process Explorer进行查找,或者使用Response.Write(IntPtr.Size)。 - usr
1
@usr,我刚在生产服务器上使用了IntPrt.Size,它返回4,这意味着DLL正在以32位运行。此外,IIS的工作进程也是以32位应用程序运行的。我想我需要强制IIS以64位运行,这样我的问题就会得到解决?以32位运行DLL的影响是什么?顺便说一句,有时我看到总内存使用量超过了2GB(这是32位DLL的最大值)。 - Mostafa
2个回答

1
似乎问题出在长字符串上。可能是当StringBuilder追加新内容时,它想要扩展内存。我不确定这个操作什么时候发生;StringBuilder尝试将大小加倍。我相信CLR不能分配大于2GB的对象,这就是为什么会抛出OutOfMemoryException的原因。

"ExpandByABlock": StringBuilder在后续框架版本中使用小块。 - usr
我有这个想法,但我确定我没有2GB大小的对象/字符串。例如,问题中粘贴的第一个异常大小为10 KB,并且调用replace函数以删除一些单词(将它们替换为空)。所以我不确定这是否是问题! - Mostafa
也许你可以尝试运行一些分析工具并专注于内存测量。另一个可能性是,你正在尝试序列化的树实际上是带有一些循环引用的图形。 - Piotr Pasieka
@Mostafa 尝试使用选项 PreserveReferencesHandling = PreserveReferencesHandling.Objects 设置 JSON 序列化器。 - Piotr Pasieka

1
您正在看到32位地址空间的碎片化。可用的最大地址空间取决于操作系统和exe,可能为2、3或4 GB。
将IIS工作进程设置为64位,以便您的AnyCPU DLL可以利用它。

谢谢,这解决了我的问题。现在DLL可以在64位模式下工作了。 - Mostafa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接