c# - basicHttpBinding、netTcpBinding、protobuff扩展的序列化性能
问题描述
我观察到奇怪的性能问题 - 从访问 WCF 服务的三种方式:
- 最快的是通过basicHttp
- netTcp速度较慢且
- 带有 protoBuff-net 格式化程序的 netTcp比 basicHttp稍慢。
背景:我继承了一些复杂的后端应用程序,进行大量计算和数据库访问,由我们前端的后端部分调用(即浏览器调用A,A调用B,B从SQL获取数据,进行一些计算,返回它给 A,它转而做更多的计算并将其返回给浏览器)。
我们正在谈论 A <-> B 部分的性能。收到 A 的请求后,大部分数据从 B 流向 A。
WCF 是自托管的(对于本实验)。
服务通过 3 个不同的端点公开:
- basicHttpBinding 与 messageEncoding="Text" textEncoding="utf-8"
- netTcpBinding
- netTcpBinding 与 protobuf-net
我编写了一个专用的简单客户端来创建有效负载。它只是使用相同 WCF 客户端的 3 个不同实例(每个端点一个)调用服务。
调用在循环中完成(101 次迭代),第一次迭代时间被丢弃,时间用 Stopwatch 实例。
单线程同步调用,每个调用仅在前一个调用完成后开始,并且返回的实体经过验证。
被调用的服务 (B) 对每个调用执行相同的处理,并且每个调用和每个端点的返回数据都是相同的。
每个请求都有少量从客户端到 B 的原始类型,然后 B 返回List<T>
约 36K 实体,每个实体有 int、2 个字符串、2 个日期时间(所有字段都是非空的)。很多字符串都在重复(它们都属于某个具有约 100 个可能值的字典)。每个 int 值有数百个项目,日期时间或多或少是随机的。
此客户端和被调用的服务(和 SQL)在同一台计算机上运行。由于无法修改服务返回的对象,因此无法使用 protobuf-net 的属性驱动模式,只能使用代理方式。
此外,客户端不引用服务 B 中的任何实际类型,它使用 WCF 生成的代理工作(因此 protobuf 代理将自己映射到那些生成的类型)。
我希望成为最快的 protobuf,然后是带有默认二进制编码器的 tcp,然后是基于 http 的慢速文本。
实际时间不同(时间是一个请求的平均经过时间,以毫秒为单位:
- Http - 442 毫秒
- Protobuf - 445ms
- TCP - 514 毫秒
确切的数字每次都略有不同,但它们具有相同的模式 - Http 和 Protobuf 或多或少相同,Tcp 慢 10-15%。
当客户端和服务都在 Release 模式下编译时完成测量任何 CPU 并从命令行运行,在 Win10 64 位和 16G Ram 上。
时间还包括 B 完成的处理,从 SQL 中获取数据等,因此它们本身没有意义。
所以,任何人都知道我做错了什么,或者为什么 Http 突然成为马厩中最快的马?:)
我上一次(也是第一次)接触 WCF 是在大约 13 年前,编写代码的人也不是 WCF 专家,所以我可能忽略了一些明显的事情。
解决方案
推荐阅读
- python - PyInstaller - FileNotFoundError:没有这样的文件或目录:''
- jmeter - 用日期替换空白
- c# - 比较浮点数的总和
- ruby-on-rails - 使用 webpack 在 rails 6 视图中导入单个 css 文件的最佳方法
- bash - 为什么我不能在 shell 脚本的“else”块中引用变量 $USER?
- c# - C#get root方法中out参数问题
- email - Hubspot 将无法识别并登录到 CRM 我来自 AMndrill 的密件抄送电子邮件
- python - 在 Python 中为列表的每个元素添加 4 个字符后的字符串
- django - Django 接收到错误的参数
- amazon-cognito - 删除 AWS Amplify 添加的用户池