【发布时间】: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