【问题标题】:OutOfMemoryException - WCF servicesOutOfMemoryException - WCF 服务
【发布时间】:2015-07-28 10:41:12
【问题描述】:

我发布了一个 WCF (C#) 项目,但我面临“OutOfMemoryException”问题。 DLL 使用Any CPU 构建。 AppPool 内存设置设置为 0(表示没有限制)。 我每分钟不断有大约 1500 个请求,每分钟大约有 100 个其他请求。该项目使用 EntityFramework。应用中有缓存(是字典)

我做了一些故障排除,试图找出问题所在,但还不清楚。我试图计算使用的总内存(通过调用GC.GetTotalMemory(false))和缓存列表的大小。在获得 OOM 异常时,缓存大小约为 7 MB(2500 个对象,每个对象 30 KB),使用的总内存在 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 位的。
  • 我怎样才能得到比特? DLL 是使用“任何 CPU”设置构建的,并且服务器正在运行 Windows server 2012 x64。所以 DLL 的正常行为是 64!
  • DLL 占用了托管进程的位数。使用 Process Explorer 查找,或 Response.Write(IntPtr.Size)。
  • @usr,我刚才在生产服务器上使用了 IntPrt.Size,它返回 4,这意味着 DLL 以 32 位运行。同样,IIS 的工作进程作为 32 位应用程序运行。我想我需要做的是强制 IIS 以 64 位运行,我的问题会解决吗?将 DLL 作为 32 位运行有什么影响?附言我看到使用的总内存有时超过 2GB(这是 32 位 DLL 的最大值)。

标签: c# .net string wcf out-of-memory


【解决方案1】:

您看到 32 位的地址空间碎片。最大可用地址空间取决于操作系统和 exe,冷为 2,3 或 4 GB。

以 64 位运行 IIS 工作进程,以便您的 AnyCPU DLL 可以利用它。

【讨论】:

  • 谢谢,这解决了我的问题。 DLL 现在在 64 位模式下工作。
【解决方案2】:

似乎问题出在长字符串上。可能StringBuilder 在追加新内容时想要扩展内存。我不确定,但何时进行此操作; StringBuilder 尝试双倍尺寸。我相信 CLR 不能分配大于 2GB 的对象,这就是为什么它会抛出 OutOfMemoryException

【讨论】:

  • "ExpandByABlock":StringBuilder 在以后的框架版本中使用小块。
  • 我有这个想法,但我确信我没有 2GB 大小的对象/字符串。例如,粘贴在问题中的第一个异常大小为 10 KB,调用 replace 函数删除一些单词(将它们替换为空)。所以我不确定这个问题!
  • 也许您可以托盘运行一些分析工具并专注于内存测量。另一种可能性是您尝试序列化的树实际上是带有一些循环引用的图
  • @Mostafa 尝试使用选项 PreserveReferencesHandling = PreserveReferencesHandling.Objects 设置 json 序列化程序
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-14
  • 2011-04-22
  • 1970-01-01
  • 2011-04-27
  • 2012-01-14
  • 1970-01-01
相关资源
最近更新 更多