我一直在一个服务器上工作,该服务器接收来自另一台服务器的请求,计算该值,然后通过TCP返回结果。
对于后端开发我还是很新的。上个月,从每秒20000个响应到80000个响应,我学到了很多东西,并将它们应用于此服务器:预先分配byte []缓冲区,非分配api调用,TPL Dataflow,线程。
基本上,所有处理现在都移到了处理管道中,网络接收/发送是在它们自己的单线程上。
但是,整体性能仍然受到网络IO的限制,而网络IO是通过TCPClient实现的。
实施
- 使用的NetworkStream R / W方法是阻止方法。首先读取4个字节以获取长度,头读取2个字节,然后读取N个字节作为消息正文。
- 我使用以 BufferSegmentPointer 命名的byte []缓冲区包装对象。这些对象已使用一定长度(> 2048)的byte []进行了预初始化。
- BufferSegmentPointer 沿着TPL数据流管道传输,一旦处理了请求,结果是将Buffer.BlockCopy()放入缓冲区,将使用的byte []范围记录在其上,然后将通过管道发送到NET OUTPUT,因此NetworkStream.Write()只知道要写什么。
- 管道的处理段是一个TransformBlock,其MaxDegreeOfParallism设置为Enviromnet.ProcessorCount-2。
测试统计信息
该程序只是 IN > 处理> OUT 的管道。
其中可以分为5个部分:
NET IN > IN Transfer > 处理> Out Transfer > NET OUT >
请注意,由于VM上的测试客户端无法发送足够的请求,因此以下VM的测试结果受到限制。 这是我现在的瓶颈。 NetworkStream IO线程读/写太慢。
请注意,如果我将数十个请求捆绑到一个NetworkStream.Write()调用中,它的性能会明显提高,但这是没有意义的,因为在实际的生产场景中永远不会捆绑请求。
请注意,如果我只是从测试客户端写入2GB的byte [],然后通过服务器接收它,则需要0.8秒。 (本文中提到的所有测试都是在本地主机上执行的。)
测试1:TCP I
测试客户端在循环中发送的1000000请求702字节。
秒表在收到第一个秒表时开始,在收到所有秒表时停止。
O> X> X> X> X (未通过数据流传输,收到后立即计数)
结果
-
在ESXi VM 2.4GHz上
- 12.99s * 12 在i5-7500 3.4GHz * 4上
- 5.86s
测试2:TCP O
用于测试写入吞吐量。
1000000 NetworkStream.Write()调用N个字节。
秒表在第一个发送之前开始,在所有发送结束后停止。
X> X> X> X> O
结果
-
ESXi VM 2.4GHz上
- 8.42s N = 653 * 12
- 4.75s ,N = 577,在i5-7500 3.4GHz * 4
测试3:TCP IO
测试客户端在循环中发送的1000000请求702字节。
1000000响应,500〜700字节,因为使用了随机结果。
秒表在测试客户端发送第一个请求之前启动,在收到所有响应后停止。
O> X> X> X> O
(请求未通过数据流传输,收到后立即计数)
(响应已创建并事先转换为byte [],只要收到请求就将其写入一次)
结果
- 11.7秒在ESXi VM 2.4GHz * 12 上 在i5-7500 3.4GHz * 4上
- 5.74s
测试4:本地处理
1000000个702字节的请求,由服务器自身生成。
没有响应,一旦完成处理调用,处理的计数器++。
秒表在第一个请求馈入管道之前启动,在处理的计数器达到1000000时停止。
X> O> O> X> X
结果
-
ESXi VM 2.4GHz上的
- 6.89s * 12 在i5-7500 3.4GHz * 4上
- 8.28s
测试5:生产测试
包括处理。 测试客户端循环发送1000000个请求(702字节)。
1000000响应,500〜700字节,因为使用了随机结果。
秒表在测试客户端发送第一个请求之前启动,在收到所有响应后停止。
O> O> O> O> O
结果
-
ESXi VM 2.4GHz上
- 18.6s * 12 在i5-7500 3.4GHz * 4上
- 11.8s
我的问题
- 非阻塞(异步)呼叫会有所帮助吗?
- SAEA(SocketasyncEventArgs)是否有可能击败TCPClient?我看到套接字方法将尽可能尝试使用SAEA,而TCPClient只是包装器……
- 您是否认为瓶颈可能在哪里?
- 我的主管可以使用JAVA发送超过300000 / s的请求(> 200mb / s),这真的是JAVA超出了.NET的性能,还是我很愚蠢?
- 由于NetworkStream R / W在办公室PC(i5)上的性能优于VM,因此我相信NetworkStream受单核(线程)性能的限制(此假设是否正确?),但我需要知道为什么这么慢?一定要这么慢吗?