与实体框架并行.与启动多个可执行文件相比,性能是巨大的,为什么?

Ben*_*ens 9 parallel-processing performance frameworks entity entity-framework

我想知道你们中是否有人知道为什么我的表现很糟糕;

我想要实现的目标; 生成220万个文件.要创建每个文件,平均需要2-5个数据库调用.

我正在处理的服务器有24个内核和190GB的RAM.

我将需要生成的文件分为24个批次.

乳清我使用下面的代码,我的表现很糟糕.生成过程需要一个多小时.

Parrallel.ForEach(batches, batch => 
{
    using (var ctx = new MyContext())
    {
        for each(var file in batch.Files)
        {
            GenerateFile(file);
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

但是,当我确保我的程序收到一个参数,以便progam知道要生成哪个批处理,所以我不需要使用并行功能.如果我使用以下.bat文件为每个批处理执行程序;

START CaMaakEiBericht.exe \B1
START CaMaakEiBericht.exe \B2
...
START CaMaakEiBericht.exe \B24
Run Code Online (Sandbox Code Playgroud)

它的运行速度惊人!总生成过程不到15分钟!此批处理文件还确保每个核心的CPU使用率约为90%.当我使用Parallel方法时,我只能获得30-40%的使用率.

有人对此有合理的解释吗?我对这个项目感到很满意,因为我终于有可能将.NET 4 Parallel库与EF结合使用,但不幸的是,它让我很失望:-)

我个人有点怀疑EF是这里的瓶颈......它是否在内部缓存一些东西,当多个进程获取数据时会强加一些锁?

开导我 :-)

Cod*_*hug 4

我无法解释为什么您的其他 EXE 文件运行良好,但我可以为您提供的代码提供建议。

您提到您将工作分成 24 个批次,然后在批次列表上使用 ForEach。通过此设置,我们的 24 个内核中的每一个似乎都可以一次处理 1 个文件。我的猜测是这是你的瓶颈。

如果你愿意的话,每个核心都可以做更多的事情。尝试这样的事情:

Parallel.ForEach(batches, batch => 
{
    Parallel.ForEach(batch.Files, file =>
    {
        using (var ctx = new MyContext())
        {
            GenerateFile(file);
        }     
    }
});
Run Code Online (Sandbox Code Playgroud)

或者您可以完全删除批次并为其提供完整的文件列表。任务并行库将为您处理使用多个核心的问题。

Parallel.ForEach(Files, file => 
{
    using (var ctx = new MyContext())
    {
        GenerateFile(file);
    }     
});
Run Code Online (Sandbox Code Playgroud)

您可能已经知道这一点,但请记住,上下文不是线程安全的,因此您必须在最内部的 Parallel.ForEach 结构中创建一个新的上下文。