【问题标题】:Parallel.Foreach gets frozen but service continues to respondParallel.Foreach 被冻结但服务继续响应
【发布时间】:2017-02-14 04:49:12
【问题描述】:

设计: 我的 C# WCF 进程必须在内存中缓存大量数据(作为字典) - 进程占用的内存增长超过 1.5GB。缓存中的数据或多或少来自数据库(使用实体框架)。缓存的构建方式是: 在表上选择查询以从表中获取主键列表(例如字符串列表)。假设我得到一个包含 1000 个项目的列表。 现在我在这个主键列表上执行 Parallel.Foreach 并且(foreach 的主体)操作是转到数据库并获取该键的所有数据(即从 KeyColumn = 循环项的表中选择 *)。对数据进行一些操作,然后将其添加到缓存(字典)中。

问题: 当进程/可执行文件启动时。它消耗了几乎 95% 的 CPU(这很好)并且占用了 RAM(比如 1.3 或 1.4 GB)。运行良好,直到前 10-12 分钟。但是后来不知什么原因,CPU 下降到 15-17% RAM,稳定在 1.4GB(还有更多)。而且我可以看到数据库中的几个项目尚未添加到缓存中。这种 Frozen 状态会持续很长时间(有时 10 小时),然后一切都会处理,所有数据都在我的缓存中。 RAM 现在稳定在 1.5GB 左右。我认为 GC 周期会冻结应用程序线程,但随后(因为它是 WCF 服务)任何服务方法调用都会响应。它只是那个似乎每次都冻结的并行线程部分,每次重新启动时都以相同的 RAM 大小......而且数据方面每次都从缓存中丢失相同的一组项目。 我已经验证了那些众所周知的缺失键的数据没有什么不同。

寻找任何关于似乎有问题的指针?

编辑

简单来说,我的代码流程如下:

ConcurrentDictionary<string, string> MyCache = new ConcurrentDictionary<string, string>();

private List<string> GetPrimaryKeysFromDB()
{
using(var ctx = new MyDBContext())
{
List<string> results = ctx.MyTable.Select(x=>x.PrimeColumn).ToList();
return results;
}
}

private void SomeMethod()
{
List<string> ListOfPrimeItems = GetPrimaryKeysFromDB();

Parallel.Foreach(ListOfPrimeItems, #MaxDopSetting#, k =>
  {
ProcessDataForKey(k);
  });
}

private void ProcessDataForKey(string key)
{
// Goto DB and fetch record for key
// Each column (Entity data member) will undergo some processing here
// some string manipulations
// Finally convert the new state of data to XML (serialize) and store in cache
MyCache[key] = TranslatedStateOfData;
}

【问题讨论】:

  • 错的是不要那样做。如果您的数据库太慢,请让它更快,那么缓存层就是 1990 年代。除此之外,请查看 ParallelOptions.MaxDegreeofParallelism,将其设置为您拥有的核心数量或最多翻倍。
  • 感谢您的回复本。但是,我需要转换数据的高/快速可用性(因此是缓存)。默认MaxDOP设置不是最推荐的一种来源:link
  • 您需要更多信息来调试此类问题。您的代码中的任何行(与 .NET 框架相反)是否在“爬行”时执行?你有一些Minimal, Complete, and Verifiable code 供我们试用吗?通常这种爬取是两件事的结果:Thrashing 或等待/同步
  • 你的机器有多少内存?它是64位进程吗?一旦超过物理 RAM,您将开始分页,一切都会变慢。一旦超过一定比例的物理 RAM,就会开始进行垃圾收集以恢复内存。在我看来,您只是没有足够的 RAM 和/或地址空间。
  • 这是在一个相当不错的服务器(64 位)多 CPU(我猜是 Xeon 的)上,测试机器上有大约 16 个核心(超过 32GB RAM)。将 MaxDOP 设置为 Environment.ProcessorCount 并使用 ConcurrentDictionary 而不是 Dictionary 没有帮助。情况是一样的。由于我的工作性质,无法分享大部分代码。

标签: c# .net multithreading task-parallel-library


【解决方案1】:

编写此更新,以便其他人可以从中受益。就我而言,任务并行库完美无缺。问题在于我的数据处理步骤之一。 我正在使用正则表达式,我的一个正则表达式遭受“Catastrophic Backtracking

我修复了正则表达式,它运行得非常快(几分钟内)。谢谢大家的建议,即使我发布了错误的问题。错过了这么一个小错误感觉很愚蠢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-12-01
    • 1970-01-01
    • 2019-01-20
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 2015-10-14
    • 2019-06-17
    相关资源
    最近更新 更多