asp.net应用程序的物理内存太多了?

时间:2008-11-10 14:02:16

标签: asp.net memory memory-leaks

我的32位基于Web服务的基于LLBLGen的数据访问应用程序在专用的64位计算机上独立运行。当进程释放几乎所有分配的空间(高达1,5GB)并且从那一点再次继续增长时,它的物理内存消耗稳定增长到大约2GB。页面输入值或其他页面文件使用参数没有可观察到的增加,因此看起来内存被释放而不是被换出到页面文件。我在想这是什么样的个人资料?实际上没有什么可以防止进程占用所有内存,另一方面内存释放周围存在不可接受的http内部错误 - 可能是清理阻止了有用的工作。如果上述情况首先是一种可接受的行为,那么使清理变得不那么突兀的好策略是什么。

8 个答案:

答案 0 :(得分:2)

听起来你有内存泄漏,进程一直在泄漏内存,直到它因内存不足而崩溃,然后由服务器自动重启。

1.5GB大约是32位进程在用完地址空间之前可以分配的最大内存量。

要寻找的事情:

  • 你自己做缓存吗?什么时候从缓存中删除项目?
  • 是否有某个地方的数据偶尔被添加到集合中但从未删除过?
  • 您是否在每个实现IDisposable的对象上调用Dispose?
  • 您是否访问任何非托管代码(COM对象或使用DllImport)或分配非托管内存(例如使用Marshal类)?任何分配在那里的东西都不会被垃圾收集器释放,你必须自己释放它。
  • 您是否使用第三方图书馆或第三方的任何代码?它也可以在列表中出现任何问题。

答案 1 :(得分:1)

您是否有可能不处理各种一次性物品(特别是与DB相关的物品)。这会留下它们,可能会占用大量非托管资源,直到GC运行并调用它们的终结器。

值得对你的进程运行perfmon,并查看某些关键资源(如句柄)是否有稳定增长,或者数据库提供程序是否公开性能计数器,然后是连接或打开结果集。

答案 2 :(得分:1)

我同意edg的答案的第一部分,但他说:

  

“通过将对象设置为null   死了你可以鼓励GC   重用那些消耗的内存   对象,这限制了增长   消耗记忆。“

不正确。您永远不需要将对象设置为null,因为GC最终会在超出范围后收集对象。

这在SO:Setting Objects to Null/Nothing after use in .NET

的答案中讨论过

答案 3 :(得分:0)

垃圾收集器在释放对象时不会自动释放内存,它会保留内存以帮助最大限度地降低未来malloc的费用。

当触发低内存条件时,内存将返回到操作系统,并且在查看任务管理器时您将看到更多可用内存。这通常发生在2GB标记左右,如果使用relevant switch,则通常为3GB。

<contentious>

通过将对象设置为null时,可以鼓励GC重用这些对象消耗的内存,这限制了内存消耗的增长。

但是你应该将哪些对象设置为null?大对象,大型集合,经常创建的对象。

</contentious>

编辑:有证据支持将对象设置为null的值。有关详细信息,请参阅this。当然没有需要将对象设置为null,重点是它是否有助于内存管理?

编辑:如果存在这样的事情而不是继续发表意见,我们需要最近的基准。

答案 4 :(得分:0)

不要使用Arraylists(垃圾收集不与它们一起工作),而是使用通用列表

其他常见错误是在web.config Debug = true中,这会消耗大量内存,将选项更改为“false”。

要做的其他事情是使用CLRProfiler来追踪问题。

祝你好运, 佩德罗

答案 5 :(得分:0)

确保您没有提供项目的调试版本。有一个功能*,当你有一个调试版本时,如果你实例化包含事件定义的任何对象,即使你没有引发事件,它也只能无限期地保存一小段内存。随着时间的推移,这些小块内存将耗尽您的内存池,直到它最终重新启动Web进程,然后重新开始。

*我称这是一个功能(而不是一个bug),因为它自.Net 2开始以来一直存在(不存在于.Net 1.1中),并且没有修补它的补丁。内存泄漏必须归因于调试时需要的一些功能。

答案 6 :(得分:0)

我们遇到了类似的情况并改变了我们所有的数据库连接以使用try / catch / finally方法。 Try用于执行代码,catch用于错误收集,最后用于关闭所有变量和数据库连接。

internal BECollection<ReportEntity> GetSomeReport()
    {
        Database db = DatabaseFactory.CreateDatabase();
        BECollection<ReportEntity> _ind = new BECollection<ReportEntity>();
        System.Data.Common.DbCommand dbc = db.GetStoredProcCommand("storedprocedure");

        try
        {
            SqlDataReader reader = (SqlDataReader)db.ExecuteReader(dbc);
            while (reader.Read())
            {
                //populate entity
            }
        }
        catch (Exception ex)
        {
            Logging.LogMe(ex.Message.ToString(), "Error on SomeLayer/SomeReport", 1, 1);
            return null;
        }
        finally
        {
            dbc.Connection.Close();
            _ind = null;
        }
        return _ind;
    }

答案 7 :(得分:0)

我的第一个猜测是内存泄漏。我的第二个猜测是它是正常的行为 - 在你有巨大的内存压力之前,GC不会被触发。唯一可以确定的方法是使用分析器和PerfMon之类的组合。一些网站:

此外,我会确保您没有在调试模式下运行(如前所述)。

就HTTP错误而言 - 假设您在服务器GC模式下运行,它会尝试尽一切可能阻止请求。有趣的是找出那些HTTP错误 - 这不是我过去看到的正常行为,并且可能指出你问题的根源。