背景
我有一个应用程序接收定期数据转储(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 团队提供了反馈。请参阅我的答案以获取摘要。