14

背景

我有一个应用程序接收定期数据转储(XML 文件)并使用 Entity Framework 5(代码优先)将它们导入现有数据库。导入是通过 EF5 而不是 BULK INSERT 或 BCP 进行的,因为必须应用实体中已经存在的业务规则。

处理似乎在应用程序本身中受 CPU 限制(极快的、启用写入缓存的磁盘 IO 子系统在整个过程中显示几乎为零的磁盘等待时间,而 SQL Server 显示不超过 8%-10% 的 CPU 时间)。

为了提高效率,我使用带有组件的TPL Dataflow 构建了一个管道,用于:

Read & Parse XML file
        |
        V
Create entities from XML Node
        |
        V
Batch entities (BatchBlock, currently n=200)
        |
        V
Create new DbContext / insert batched entities / ctx.SaveChanges()

我看到这样做可以显着提高性能,但不能使 CPU 超过 60%。

分析

怀疑某种资源争用,我使用 VS2012 Profiler 的资源争用数据(并发)模式运行该过程。

分析器向我显示标记为Handle 2的资源的争用率为 52% 。深入研究,我看到为Handle 2创建最多争用的方法是

System.Data.Entity.Internal.InternalContext.SaveChanges()

第二位,大约是 SaveChanges() 的 40%,是

System.Data.Entity.DbSet`1.Add(!0)

问题

  • 我怎样才能弄清楚Handle 2到底是什么(例如 TPL 的一部分,EF 的一部分)?
  • EF 是否会限制从单独线程中分离 DbContext 实例的调用?他们似乎在争夺一个共享资源。
  • 在这种情况下,我可以做些什么来提高并行性?

更新

对于有问题的运行,调用 SaveChanges 的任务的最大并行度设置为 12(我在以前的运行中尝试了各种值,包括 Unbounded)。

更新 2

Microsoft 的 EF 团队提供了反馈。请参阅我的答案以获取摘要。

4

1 回答 1

5

下面总结了我与实体框架团队在这个问题上的互动。如果有更多信息,我会更新答案

  • 该问题可以在 Microsoft 重现。
  • 句柄争用与网络 I/O 相关(即使使用本地主机上的 SQL Server)。具体来说,System.Data.dll 中网络 I/O 的读取缓冲区存在争用。
  • EF 团队现在正在与 SQL Connectivity 团队合作,以更好地了解该问题。
  • 微软目前还没有关于如何最小化这种争用的影响的指导。

更新

现在正在 CodePlex 上跟踪此问题:

http://entityframework.codeplex.com/workitem/636?PendingVoteId=636

于 2012-11-12T19:24:39.733 回答