【问题标题】:.NET JIT Code Cache leaking?.NET JIT 代码缓存泄漏?
【发布时间】:2010-02-25 14:12:59
【问题描述】:

我们有一个用 .Net 3.5 编写的服务器组件。它在 Windows Server 2008 标准版上作为服务运行。它运行良好,但经过一段时间(几天)后,我们注意到速度大幅放缓,工作量增加。我们预计会发生某种内存泄漏,并使用 WinDBG/SOS 来分析进程的转储。不幸的是,GC 堆没有显示任何泄漏,但我们注意到 JIT 代码堆从开始后的 8MB 增长到几天后的 1GB 以上。

我们自己不使用任何动态代码生成技术。我们使用以动态代码生成而闻名的 Linq2SQL,但我们不知道它是否会导致这样的问题。

主要问题是是否有任何技术可以分析转储并检查 WinDBG 转储中显示的所有主机代码堆块来自何处?

[更新]

与此同时,我们进行了更多分析,并认为 Linq2SQL 可能是可疑的,尤其是因为我们不使用预编译查询。以下示例程序创建的行为完全相同,随着时间的推移会创建越来越多的主机代码堆块。

using System;
using System.Linq;
using System.Threading;

namespace LinqStressTest
{
    class Program
    {
        static void Main(string[] args)
        {
            for (int i = 0; i < 100; ++ i)
                ThreadPool.QueueUserWorkItem(Worker);
            while(runs < 1000000)            
            {
                Thread.Sleep(5000);
            }
        }

        static void Worker(object state)
        {
            for (int i = 0; i < 50; ++i)
            {
                using (var ctx = new DataClasses1DataContext())
                {
                    long id = rnd.Next();
                    var x = ctx.AccountNucleusInfos.Where(an => an.Account.SimPlayers.First().Id == id).SingleOrDefault();
                }
            }
            var localruns = Interlocked.Add(ref runs, 1);
            System.Console.WriteLine("Action: " + localruns);
            ThreadPool.QueueUserWorkItem(Worker);
        }

        static Random rnd = new Random();
        static long runs = 0;
    }
}

当我们用预编译的查询替换 Linq 查询时,问题似乎消失了。

【问题讨论】:

  • @pitchfork - 一个随机的想法。您是否尝试关闭 DataContext 中的更改跟踪? ctx.ObjectTrackingEnabled = false 作为 using 语句的第一行?

标签: c# memory-leaks


【解决方案1】:

使用“单例”DataContext,而不是一直在循环中重新创建它。

我相信效果会和编译查询一样。

更新:

这个问题应该在 .NET 4 中得到“纠正”,因为它支持 GC'able 动态程序集。

【讨论】:

    【解决方案2】:

    我知道 .net 中内存泄漏的唯一方法是由于事件处理,请查看:

    1. link1
    2. 另外,看看下面的问题:How do I avoid a memory leak with LINQ-To-SQL?
    3. 另外,看看 ANTS 分析器
    4. 而且,您是否考虑过,在某些时候您可能会运行许多线程?哪个会自然消耗大量内存?

    【讨论】:

    • 感谢您的提示。使用 WinDBG,我们能够证明我们没有在托管堆中泄漏内存,而且我们总是在工作单元完成后通过我们的 DataContext。
    猜你喜欢
    • 2011-03-18
    • 2015-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2010-12-07
    • 1970-01-01
    相关资源
    最近更新 更多