.NET JIT代码缓存泄漏?

时间:2010-02-25 14:12:59

标签: c# memory-leaks

我们有一个用.Net 3.5编写的服务器组件。它作为Windows Server 2008 Standard Edition上的服务运行。它运作良好,但经过一段时间(天),我们注意到大幅减速和增加工作量。我们期望某种内存泄漏并使用WinDBG / SOS来分析进程的转储。不幸的是,GC Heap没有显示任何泄漏,但我们注意到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查询替换Linq查询时,问题似乎消失了。

2 个答案:

答案 0 :(得分:1)

使用'singleton'DataContext,而不是在循环中一直重新创建它。

我确信效果与编译的查询相同。

<强>更新

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

答案 1 :(得分:0)

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

  1. link1
  2. 另外,请看一下以下问题:How do I avoid a memory leak with LINQ-To-SQL?
  3. 另外,请查看ANTS探查器
  4. 并且,你有没有考虑过,或许,在某些时候你会有很多线程在运行?哪个会天真地消耗大量内存?