NetworkStream线程瓶颈 测试1:TCP I 测试2:TCP O 测试3:TCP IO 测试4:本地处理测试5:生产测试

我一直在一个服务器上工作,该服务器接收来自另一台服务器的请求,计算该值,然后通过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

我的问题

  1. 非阻塞(异步)呼叫会有所帮助吗?
  2. SAEA(SocketasyncEventArgs)是否有可能击败TCPClient?我看到套接字方法将尽可能尝试使用SAEA,而TCPClient只是包装器……
  3. 您是否认为瓶颈可能在哪里?
  4. 我的主管可以使用JAVA发送超过300000 / s的请求(> 200mb / s),这真的是JAVA超出了.NET的性能,还是我很愚蠢?
  5. 由于NetworkStream R / W在办公室PC(i5)上的性能优于VM,因此我相信NetworkStream受单核(线程)性能的限制(此假设是否正确?),但我需要知道为什么这么慢?一定要这么慢吗?
zhuangting 回答:NetworkStream线程瓶颈 测试1:TCP I 测试2:TCP O 测试3:TCP IO 测试4:本地处理测试5:生产测试

暂时没有好的解决方案,如果你有好的解决方案,请发邮件至:iooj@foxmail.com
本文链接:https://www.f2er.com/3151018.html

大家都在问