title: Entity Framework and Parallelism
body: <p><strong>Background</strong></p>
  
  <p>I have an application that receives periodic data dumps (XML files) and imports them into an existing database using Entity Framework 5 (Code First).  The import happens via EF5 rather than say BULK INSERT or BCP because business rules that already exist in the entities must be applied.</p>
  
  <p>Processing seems to be CPU bound in the application itself (the extremely fast, write-cache enabled disk IO subsystem shows almost zero disk wait time throughout the process, and SQL Server shows no more than 8%-10% CPU time).</p>
  
  <p>To improve efficiency, I built a <a href="http://msdn.microsoft.com/en-us/library/hh228604.aspx" rel="noreferrer">pipeline using TPL Dataflow</a> with components to:</p>
  
  <pre><code>Read &amp; 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()
  </code></pre>
  
  <p>I see a substantial increase in performance by doing this, but can not get the CPU above about 60%.  </p>
  
  <p><strong>Analysis</strong></p>
  
  <p>Suspecting some sort of resource contention, I ran the process using the VS2012 Profiler's <em>Resource contention data (concurrency)</em> mode.</p>
  
  <p>The profiler shows me 52% contention for a resource labeled <em>Handle 2</em>.  Drilling in, I see that the method creating the most contention for <em>Handle 2</em> is </p>
  
  <pre><code>System.Data.Entity.Internal.InternalContext.SaveChanges()
  </code></pre>
  
  <p>Second place, at about 40% as many contentions as SaveChanges(), is</p>
  
  <pre><code>System.Data.Entity.DbSet`1.Add(!0)
  </code></pre>
  
  <p><strong>Questions</strong></p>
  
  <ul>
  <li>How can I figure out what <em>Handle 2</em> really is (e.g. part of TPL, part of EF)?</li>
  <li>Does EF throttle calls to separate DbContext instances from separate threads?  It seems there is a shared resource they are contending for.</li>
  <li>Is there anything that I can do to improve parallelism in this case?</li>
  </ul>
  
  <p><strong>UPDATE</strong></p>
  
  <p>For the run in question, the maximum degree of parallelism for the task that calls SaveChanges is set to 12 (I tried various values including Unbounded in previous runs).</p>
  
  <p><strong>UPDATE 2</strong></p>
  
  <p>Microsoft's EF team has provided feedback.  See my answer for a summary.</p>