【问题标题】:Possibly memory leak OR?可能是内存泄漏或?
【发布时间】:2012-08-19 04:40:59
【问题描述】:

在此不胜感激。

关于场景的简要说明 -

服务器上运行着一个 COM+(用 C# 编写)。该 COM 的任务是获取多页 tiff 文件的文件名、页码以及将其转换为 gif 文件图像的分辨率。使用代理从 Web 应用程序调用此 COM。网站获取转换后的图像并以请求的分辨率显示。对于打印 - 它发出 2 个请求 - 第一个用于显示分辨率,第二个为全分辨率(使用 window.print() 打印)。

问题-

一段时间后,服务器内存不足,图像没有显示在网站上。服务器需要定期重启。

错误

EventType clr20r3, P1 imageCOM.exe, P2 1.0.0.0, P3 4fd65854, P4 prod.web.imaging, P5 1.0.0.0, P6 4fd65853, P7 1a, P8 21, P9 system.outofmemoryexception, P10 NIL.

Here is the error(s) on the web server (these continuously appear every minute) ….

System.Net.WebException: Unable to connect to the remote server ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it
   at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
   at System.Net.Sockets.Socket.InternalConnect(EndPoint remoteEP)
   at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Int32 timeout, Exception& exception)
   --- End of inner exception stack trace ---

我无权访问生产服务器,但系统管理员发送的错误指出 OutOfMemory。

因此,假设内存泄漏并专注于它 - 我到目前为止的发现,处理这种情况的经验有限 -

  • Perfmon - 我看到进程/私有字节正在增加,因此也在增加 .Net CLR 内存/堆中的字节数。因此,我认为它是托管的 内存泄漏。不过我不确定。
  • CPU 使用率 - 从 8% 开始,仅在开始时上升到 80%。 它回落并保持在 3% - 12% 之间,除了几个 当它回到 75%-85% 的时候。不知道发生了什么 在这里。
  • 我开始调试服务器 COM 看看堆、gcroot 等。

    1. 每次发出请求时,堆中的计数都在增加 2 个对象。 1 个对象是保存图像数据的对象。第二个对象是事件处理程序,用于在对象 1(图像)在特定时间后过期时从缓存中删除它。
    2. 查看方法调用 - 两个对象都指向同一个方法。
    3. 明智的代码实施 - 请求的图像被缓存(达到一定数量) - 我可以理解这是为了更好的性能。可能这就是第 1 条中提到的堆中对对象的引用增加的原因。

我知道我给出了非常模糊的描述,但我需要某种线索来检测服务器上的真正问题。

编辑: 图像对象已被处理

Bitmap retVal;

      using (MemoryStream buffer = new MemoryStream(doc.FileData, 0, doc.DocumentSize, false, false))
      {
        using (Bitmap original = new Bitmap(buffer))
        {
        //select the page to convert and
        //perform scaling - full resolution or the requested resolution.  
        }
      }

      using (MemoryStream buffer = new MemoryStream())
      {
        retVal.Save(buffer, ImageFormat.Gif);
        retVal.Dispose();
        return buffer.GetBuffer();
      }

【问题讨论】:

  • “句柄”或“gdi 对象”的值是否在增加?
  • Here's the go-to answer关于如何正确处理物品,如果您想详细了解为什么需要这样做,并且要小心处理。
  • @ken2k - 我没有观察到这两个计数器。我会抓拍回来。

标签: c# asp.net .net memory-leaks


【解决方案1】:

我认为您的第一点可能是问题的原因。您可以尝试减少缓存过期时间并检查再次出现内存不足错误所花费的时间,您可能必须更改算法以避免这种情况。你的第二个不应该是错误的原因。

【讨论】:

  • 如何检查对象 1 是否已释放?您是指查看堆和 gcroot 吗?就像我说的那样,我的知识在这里有限。
  • 您的回答将我引向正确的方向。所有问题尚未解决,但我能够检测到其中一个大内存泄漏。谢谢。
  • 太好了,我很高兴它有帮助。
【解决方案2】:

确保在使用完 Image 对象(例如 Bitmap)后将其释放。我猜您正在将 tiff 图像作为位图打开并重新缩放,然后再次将其保存为 gif。如果您不处理 Bitmap,它会泄漏内存(通常每次几 MB,具体取决于图像的大小)。

【讨论】:

  • 沿着这条线:确保实现IDisposable所有东西都被正确处理。最容易记住的方法是合并using 语句:using (System.Drawing.Bitmap b = new System.Drawing.Bitmap(...)) { /* Do stuff */ }; (它会为您处理它,而不会强迫您致电 .Dispose())。
  • @Cory - 已通过合并 using 语句处理图像对象。
  • 我已经编辑了我的原始消息以显示图像是如何被处理的。如果没有正确完成请指出。另一点是图像的缩放是使用不安全的 C++ 代码完成的。我看到它在开头有 LockBits,在结尾有 UnlockBits,所以假设也有对象被正确处理。有什么想法!
猜你喜欢
  • 2011-08-12
  • 2011-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-23
  • 1970-01-01
相关资源
最近更新 更多