阻止EF性能的SNIReadSyncOverAsync和WaitForSingleObject?

时间:2012-09-29 15:29:00

标签: c# .net entity-framework entity-framework-4

我正在对使用EF(System.Data.Entities)从sql DB读取的WCF服务进行一些分析。当我启动多个达到服务的并行客户端时,CPU都会达到100%,性能通常是坦克,一切都陷入困境。

在使用并发分析器进行分析时,我发现85%的时间花在同步上,只有大约4%是实际的代码执行。深入研究堆栈跟踪,大多数同步似乎来自System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync中对WaitForSingleObject的调用。堆栈显示调用转到本机方法包装器,然后结束于kernel32.dll!_WaitForSingleObject。

以前有没有人经历过这个?对此有什么办法吗?我并没有真正抛出荒谬的负载,只有大约20个并行客户端,而且它都是只读的,所以我很惊讶线程甚至会费心去同步。

我一直在与这个斗争一个星期,我无法解释。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:2)

您是否可以将其提炼为可以重现问题的小代码示例?您使用的是哪个版本的EF?

以下是根据您目前提供的信息进行的一些观察。

EF Async

小于EF 6的任何内容始终同步。使用EF 6,您可以选择使用async methods instead。但是,除非您的WCF服务也使用异步模式,否则不要这样做。

WCF异步

您可以编写实现异步的WCF服务。有关详细信息,请参阅this documentation

如果您使用上述方法的一个,而不是两者,您的代码将不会异步,但会产生不必要的同步开销。特别要避免使用Task.Run()或等价物,因为这些只会将工作转移到另一个线程而不会实际提高吞吐量。

初始化

最后,另一个无关的想法。您的问题可能与EF初始化有关吗?当EF为模型构建元数据时,每个连接字符串执行一次。如果多个线程尝试使用相同的模型并且该模型尚未初始化,则所有线程都将阻塞,直到初始化完成。要查看这是否是您的问题,请拨打该服务并允许其完成。然后提交您的20个并行请求。他们还能最大化CPU吗?