25

我正在对使用 EF(System.Data.Entities)从 SQL DB 读取的 WCF 服务进行一些分析。当我启动多个访问服务的并行客户端时,CPU 都达到 100%,性能普遍下降,一切都陷入困境。

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

有谁之前经历过这个吗?有什么办法可以解决这个问题吗?我并没有真正为此投入荒谬的负载,只有大约 20 个并行客户端,而且都是只读的,所以我很惊讶线程甚至会费心进行同步。

我已经为此奋斗了一个星期,我无法解释。任何帮助,将不胜感激!

4

1 回答 1

3

你能把它提炼成一个重现问题的小代码示例吗?你用的是什么版本的EF?

以下是基于您迄今为止提供的信息的一些观察结果。

EF 异步

任何低于 EF 6 的东西总是同步的。使用 EF 6,您可以选择使用异步方法。但是,除非您的 WCF 服务也使用异步模式,否则不要这样做。

WCF 异步

您可以编写一个异步实现的 WCF 服务。有关详细信息,请参阅此文档

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

初始化

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

于 2013-11-07T18:28:13.547 回答