C# 控制内存庞大的多线程应用程序

C# 控制内存庞大的多线程应用程序,c#,.net,performance,C#,.net,Performance,这是一个非常开放的问题 基本上,我有一个计算应用程序,可以为N个场景启动测试组合。 每个测试都在一个单独的专用线程中进行,包括读取大型二进制数据,对其进行处理,并将结果放到数据库中 如果线程数量太多,应用程序就会变得流氓,耗尽所有可用内存并挂起。。 利用所有CPU+RAM功能的最有效方法是什么(高性能计算,即12核/16GB RAM)而不必让系统屈服(如果同时启动了“太多”线程,则会发生这种情况,“太多”当然是一个相对的概念) 我必须指定我有一个包含N个工人的工人缓冲队列,每次一个工人完成并死亡

这是一个非常开放的问题

基本上,我有一个计算应用程序,可以为N个场景启动测试组合。
每个测试都在一个单独的专用线程中进行,包括读取大型二进制数据,对其进行处理,并将结果放到数据库中

如果线程数量太多,应用程序就会变得流氓,耗尽所有可用内存并挂起。。 利用所有CPU+RAM功能的最有效方法是什么(高性能计算,即12核/16GB RAM)而不必让系统屈服(如果同时启动了“太多”线程,则会发生这种情况,“太多”当然是一个相对的概念)

我必须指定我有一个包含N个工人的工人缓冲队列,每次一个工人完成并死亡时,通过队列启动一个新的工人缓冲队列。到目前为止,这个工作还不错。但我希望避免“手动”和“经验”设置同时线程的数量,并拥有一个智能可扩展系统,该系统一次丢弃系统能够正确处理的尽可能多的线程,并在“合理”的内存使用情况下停止(目标服务器专用于应用程序,因此除了系统之外,其他应用程序没有问题)

PS:我知道.NET3.5附带了线程池,.NET4具有有趣的TPL功能,我现在仍在考虑这一点(到目前为止,我从未深入研究过这一点)

PS 2:读完后,我对“不要这样做”的答案有点困惑。尽管我认为这样的要求对于一个需要内存的计算程序来说是公平的

编辑

阅读后,我将尝试使用

所有.NET中的内置线程功能都不支持根据内存使用情况进行调整。您需要自己构建

您可以预测内存使用情况,也可以对内存不足的情况作出反应。备选方案:

  • 在启动新任务之前,请查看系统上的可用内存量。如果低于500mb,请等待释放足够的内存
  • 在任务到来时启动任务,并在其中一些任务由于OOM而开始失败时立即停止。稍后重新启动它们。这种替代方法非常耗时,因为您的进程会疯狂地进行垃圾收集以避免OOM
  • 我建议(1)

    您可以查看可用系统内存或您自己的进程内存使用情况。为了获得内存使用情况,我建议使用Process类查看私有字节


    如果您在16GB系统上留出1GB的缓冲区,您可以以94%的效率运行,而且非常安全。

    如果将性能最大化作为唯一目标,那么从1.0开始,线程池就一直在.NET中。您永远不希望线程数超过cpu核数。如果结果表明您没有足够的RAM,那么硬件就不平衡。Add更多RAM。别忘了现实检查,实际检查所有内核是否都以100%的速度最大化。如果不是,那么线程就不是解决方案。使用太多线程只会产生问题。@HansPassant是这样,但前提是线程不阻塞(文件i/o等),如果更多,可能有助于保持性能。@kenny-如果有阻塞线程,那么瓶颈就在别处。总是I/O。添加更多线程不会使I/O更快。@HansPassant为真,但它可以使CPU执行其他未阻塞的操作。是的,2肯定很糟糕:-),1就是我要做的。但我想知道在我被称为异教徒之前,我会被扔多少块石头^^有可用的代码吗?只是在这篇文章中偶然发现了WMI功能:这里的参考:听起来很有趣。我添加了一条关于如何了解内存使用情况的评论。您可以使用手动猜测的内存限制。只要确保在收到OOM时给自己发一封电子邮件,这样你就可以调整。哦,好的,我明白了。我可以使用WorkingSet64并将其限制在总系统内存的百分比内。我必须使用VisualBasic.Devices.ComputerInfo.TotalPhysicalMemory(这不是VB特有的,尽管听起来很混乱),正如Hans Passant在我在编辑中引用的pos中所建议的,不要使用工作集。工作集是当前分页的内存量(粗略地说)。它可以改变,而无需你的应用程序做任何事情!对内存计数器要非常小心。。。如我所说,使用私有字节。私有字节是指不与其他进程共享的内存。它大致相当于您的分配。不幸的是,无论是在Windows还是Linux上,都没有一个计数器可以告诉您实际的内存使用情况(由于共享,这种情况不可能存在)。