背景
我有一个应用程序,定期接收数据转储(XML文件),并使用Entity Framework 5(Code First)将它们导入到现有数据库中。导入是通过EF5而不是例如BULK INSERT或BCP进行的,因为必须应用已经存在于实体中的业务规则。
在应用程序本身中处理似乎是CPU绑定的(极快的写缓存启用的磁盘IO子系统在整个过程中几乎没有显示任何磁盘等待时间,并且SQL Server显示的CPU时间不超过8%-10%)。
为了提高效率,我构建了一个使用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的资源争用数据(并发)模式运行了该进程。
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的一部分)?
- Entity Framework会限制来自不同线程的单独DbContext实例的调用吗?似乎它们正在争夺共享资源。
- 在这种情况下,有什么可以做以提高并行性能?
更新
对于此次运行,调用SaveChanges的任务的最大并行度设置为12(我尝试了包括Unbounded在内的各种值)。
更新2
Microsoft的EF团队已经提供了反馈。请查看我的回答以获取摘要。