我们正在运行的云服务角色会大量使用线程。它带来了越来越少的100个任务。他们中的大多数都做了一些事情,然后他们睡了几分钟而不是重新开始。他们中的一些人启动服务总线队列客户端并处理多达5个并发消息。这些服务做了很多事情,但主要是数据转换:它们从数据库中取出一些内容并将它们发送到外部Web服务,或者从这些Web服务中获取内容并放在数据库上。
从我的应用程序的服务库存中,我会说不超过300个“并发”任务。
由于一些错误日志,我不得不尝试更深入,我发现了一些奇怪的东西。我试着总结一下我发现的东西以及我对它们的看法。我很乐意收到你的支票。
此应用程序是.NET 4.5.2辅助角色,为64位体系结构编译,并在2个Standard_A2中型实例(即3.5GB内存,2个核心CPU)上运行。由于Redis Caching的使用,我们调整了ThreadPool SetMinThread,如下所示:
ThreadPool.SetMinThreads(300, 300);
现在,这是我通过分析发现的:
我认为这与我们整个应用程序中的异步/等待操作有关。如果我理解正确,async / await应该使用线程池的IO完成端口部分。事实上,没有免费的IOCP,因此需要相应地提高ThreadPool的“SetMaxThread”属性。它有意义吗?
int CurrentMaxWorkerThreads = 0;
int CurrentMaxIOPorts = 0;
ThreadPool.GetMaxThreads(out CurrentMaxWorkerThreads, out CurrentMaxIOPorts);
ThreadPool.SetMaxThreads(CurrentMaxWorkerThreads, 4000);
内存使用情况:经过几天的运行(2-3天)后,我发现这个过程需要2GB。使用Ants Memory Profiler,我发现很多这个使用过的内存都是免费的,因为支离破碎(我会在第3点问这个问题)。问题是:我的应用程序不应该扩展到2GB以上吗?是否仅为32位应用程序设置了2GB限制?
内存碎片:那时候我已经读了很多关于它的内容,我真的认为试图弄清楚它为什么会发生的时间非常昂贵,即使是因为 - 使用Ants Memory Profiler - 我看到了大量的内存消耗是由于字节数组(可能是为了在应用程序之外发送内容而生成的)。现在,为了控制事情,我使用.NET 4.5.1功能压缩LOH:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();