我们有一个用 .Net 3.5 写的服务器组件。它作为服务在 Windows Server 2008 Standard Edition 上运行。它的性能非常好,但是经过一段时间(几天)后,我们注意到系统变得非常缓慢,工作集也增加了。我们认为可能是内存泄漏问题,并使用 WinDBG/SOS 分析该进程的转储文件。不幸的是,GC 堆并没有显示出任何泄漏,但我们注意到 JIT 代码堆从启动后的8MB增长到几天后的1GB以上。
我们没有使用自己的任何动态代码生成技术。我们使用 Linq2SQL,这是一个以动态代码生成而闻名的框架,但我们不知道它是否会引起这样的问题。
主要问题是是否有任何技术可以分析转储文件并检查在 WinDBG 转储中显示的所有这些 Host Code Heap 块来自哪里?
[更新]
在此期间,我们进行了更多的分析,将 Linq2SQL 视为可能的问题,特别是我们没有使用预编译查询。以下示例程序创建了完全相同的行为,随着时间推移越来越多的 Host Code Heap 块被创建。
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 查询替换原来的查询时,问题似乎消失了。
DataContext
中的更改跟踪吗?ctx.ObjectTrackingEnabled = false
作为using语句内的第一行代码? - Mike Two