如何提高 WCF 数据服务性能
我是 WCF 数据服务的新手,所以我一直在玩。经过一些初步测试后,我对测试数据服务的性能感到失望。
我意识到,由于 WCF DS 是基于 HTTP 的,因此该协议存在固有的开销,但我的测试仍然比我预期的要慢得多:
环境:
- 全部集中在一个盒子上: 四核 64 位笔记本电脑,具有 4GB RAM,运行 W7。不错的机器。
- 小型 SQL 数据库 (SQLExpress 2008 R2),有 16 个表...测试的表有 243 行。
- 使用所有默认值在 IIS 中托管我的测试服务。
代码:
- 我已经为此数据库创建了一个实体框架模型(DataContext)(VS2010 的股票代码生成)。
- 我基于这个模型创建了一个数据服务。
- 我创建了一个客户端,该客户端具有该服务的直接服务引用(ObjectContext)(VS2010 的库存代码生成)
- 在客户端中,我还可以直接调用 EF 模型,并使用本机 SQL (ADO.NET SqlConnection)
测试计划:
- 每次迭代都会连接到数据库(可以选择重用连接),查询目标表(“EVENTS”)中的所有行,然后对它们进行计数(从而强制执行任何延迟的提取)。
- 针对本机 SQL (SqlConnection/SqlCommand)、实体框架 (DataContext) 和 WCF 数据服务 (ObjectContext) 分别运行 25 次迭代。
结果:
- 本机 SQL 的 25 次迭代:436 毫秒
- 实体框架的 25 次迭代:656 毫秒
- WCF 数据服务的 25 次迭代:12110 毫秒
哎呀。这比 EF 慢大约 20 倍。
由于 WCF 数据服务是 HTTP,因此没有机会重用 HTTP 连接,因此每次迭代客户端都被迫重新连接到 Web 服务器。但肯定还有更多事情发生。
EF 本身相当快,并且服务和直接到 EF 客户端测试都重复使用相同的 EF 代码/模型。数据服务中的 Xml 序列化和反序列化会产生一些开销,但就这么多!?!我过去在 Xml 序列化方面取得了良好的性能。
我将使用 JSON 和 Protocol-Buffer 编码运行一些测试,看看是否可以获得更好的性能,但我很好奇社区是否有任何加快速度的建议。
我对 IIS 不太熟悉,所以也许可以通过一些 IIS 调整(缓存、连接池等)来改善这一点?
I'm new to WCF Data Services so I've been playing. After some initial tests I am disappointed by the performance of my test data service.
I realize that because a WCF DS is HTTP-based there is overhead inherent in the protocol but my tests are still way slower than I would expect:
Environment:
- All on one box: Quad core 64-bit laptop with 4GB RAM running W7. Decent machine.
- Small SQL database (SQLExpress 2008 R2) with 16 tables... the table under test has 243 rows.
- Hosted my test service in IIS with all defaults.
Code:
- I've created a Entity Framework model (DataContext) for this database (stock codegen by VS2010).
- I've created a data-service based on this model.
- I've created a client which has a direct service reference (ObjectContext) for this service (stock codegen by VS2010)
- In the client I am also able to call the EF model directly and also use Native SQL (ADO.NET SqlConnection)
Test Plan:
- Each iteration connects to the database (there is an option to reuse connections), queries for all rows in the target table ("EVENTS") and then counts them (thus forcing any deferred fetches to be performaed).
- Run for 25 iterations each for Native SQL (SqlConnection/SqlCommand), Entity Framework (DataContext) and WCF Data Services (ObjectContext).
Results:
- 25 iterations of Native SQL: 436ms
- 25 iterations of Entity Framework: 656ms
- 25 iterations of WCF Data Services: 12110ms
Ouch. That's about 20x slower than EF.
Since WCF Data Services is HTTP, there's no opportunity for HTTP connection reuse, so the client is forced to reconnect to the web server for each iteration. But surely there's more going on here than that.
EF itself is fairly fast and it's the same EF code/model is reused for both the service and the direct-to-EF client tests. There's going to be some overhead for Xml serialization and deserialization in the data-service, but that much!?! I've had good performance with Xml serialization in the past.
I'm going to run some tests with JSON and Protocol-Buffer encodings to see if I can get better performance, but I'm curious if the community has any advice for speeding this up.
I'm not strong with IIS, so perhaps there are some IIS tweaks (caches, connection pools, etc) that can be set to improves this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
通过启用压缩,我将 WCF 数据服务 API 的性能提高了 41%。这真的很容易做到。请点击以下链接,该链接解释了如何在 II 服务器上执行操作:为 WCF 启用动态压缩(gzip、deflate) IIS7 中的数据源、OData 和其他自定义服务
更改后不要忘记 iisReset!
在客户端:
I increased performance of our WCF Data Service API by 41% simply by enabling compression. It was really easy to do do. Follow this link that explains what to do on your IIs server: Enabling dynamic compression (gzip, deflate) for WCF Data Feeds, OData and other custom services in IIS7
Don't forget to iisReset after your change!
On the client-side:
尝试在配置的绑定部分将安全性设置为“无”。这应该会有很大的改进。
Try setting security to "none" in the binding section in the configuration. This should make big improvement.
为了消除大部分连接开销,您可以尝试将所有操作批处理到 WCF DS,看看这是否会产生显着差异。
有关详细信息,请参阅此处。
In order to eliminate most of the connection overhead you can try to batch all operations to the WCF DS to to see if that makes a significant difference.
For more info see here.
WCF DataServices 用于为您的不同客户端提供 OpenData 协议;这样您就不必为每个更改请求编写/重构多个 Web 服务方法。如果整个系统是基于微软技术堆栈的,我从不建议使用它。它适用于远程客户端。
WCF DataServices are for providing your disparate clients with OpenData protocol; so as you don't have to write/refactor multiple web service methods for each change request. I never advise it to be used if the entire system is microsoft technology stack based. It's meant for remote clients.
如何通过 WCF 的这 25 次迭代?
如果你这样调用就意味着你调用了WCF 25次,这消耗了太多的资源。
对我来说,我曾经将所有内容构建到 DataTable 中,并将用户表名称构建到我正在调用的存储过程中;
DataRow
是参数。调用时,只需使用加密形式传递 DataTable 即可。一次传递所有 25 个调用,这可以显着节省性能。如果返回对象具有相同的结构,只需将其以字节形式传递为
DataTable
,然后将其转换回DataTable
。我曾经使用 GZip 来实现此方法以导入/导出数据模块。传递大量字节会让 WCF 不高兴。这取决于你想吃什么;计算资源或网络资源。
How do you pass those 25 iterations for WCF?
If you call like that it means you call WCF 25 times, which consumes too many resources.
For me, I used to build up everything into a
DataTable
and user table name to stored procedure I'm calling;DataRow
is params. When calling, just pass the DataTable in encrypted form by usingThe thing is you pass all 25 calls at once, that can save performance significantly. If the return object is same structure, just pass it as
DataTable
in bytes form and convert it back toDataTable
.I used to implement this methods with GZip for import/export data modules. Passing large amount of bytes is going make WCF unhappy. Its depends whatever you want to consume; computing resources or networking resources.
要尝试的事情:
1)结果编码:如果可能,请使用 WCF 通道的二进制编码,请参阅 http://msdn.microsoft.com/en-us/magazine/ee294456.aspx -- 交替使用压缩:http://programmerpayback.com/2009/02/18/speed-up-your-app-by-compressing- wcf-service-responses/
2) 更改服务实例行为,请参阅 http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S6 - 尝试 InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple - 如果您可以验证您的服务是否为以线程安全的方式构建。
关于你的基准测试,我认为你应该模拟更真实的负载(包括并发用户)并忽略异常值,对 IIS 的第一个请求会非常慢(它必须加载所有 DLL)
things to try:
1) results encoding: use binary encoding of your WCF channel if possible, see http://msdn.microsoft.com/en-us/magazine/ee294456.aspx -- alternately use compression: http://programmerpayback.com/2009/02/18/speed-up-your-app-by-compressing-wcf-service-responses/
2) change your service instance behavior, see http://msdn.microsoft.com/en-us/magazine/cc163590.aspx#S6 -- try InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple - if you can verify that your service is built in a thread safe way.
Regarding your benchmark, I think you should simulate more realistic load (including concurrent users) and ignore outliers, the first request to IIS will be really slow (it has to load all the DLLs)
考虑部署为 Windows 服务? IIS 可能具有它运行的 ASAPI 过滤器、重写规则等。即使这些都不是活动的,IIS 管道也很长,某些东西可能会稍微减慢您的速度。
服务应该为您提供一个良好的基线,了解请求运行、打包等所需的时间,而不会导致 IIS 变慢
Consider deploying as a windows service instead? IIS may have ASAPI filters, rewrite rules, etc that it runs through. even if none of these are active, the IIS pipeline is so long, something may slow you down marginally.
a service should give you a good baseline of how long it takes the request to run, be packed, etc, without the IIS slowdowns
下面的链接包含一些有趣的 WCF 基准测试以及 WCF 数据服务和实体框架之间的比较的视频。
http://www.relationalis.com /articles/2011/4/10/wcf-data-services-overhead-performance.html
The link below has video that has some interesting WCF benchmarks and comparisons between WCF data services and Entity Framework.
http://www.relationalis.com/articles/2011/4/10/wcf-data-services-overhead-performance.html