I/O性能 - 异步与TPL对比数据流与RX

Eli*_*hen 18 conceptual task-parallel-library system.reactive async-await tpl-dataflow

我有一块C#5.0代码,可以生成大量的网络和磁盘I/O. 我需要并行运行此代码的多个副本.以下哪种技术可能会给我带来最佳性能:

  • 等待的异步方法

  • 直接使用TPL中的Task

  • TPL数据流nuget

  • 反应性扩展

我不太擅长这种平行的东西,但如果使用较低的杠杆,比如说Thread,可以给我更好的性能,我也会考虑.

Ana*_*tts 59

这就像试图通过最快捷的方法来移除安全带来试图优化跨大西洋航班的长度.

好的,一些真正的建议,因为我是一个混蛋

让我们给出一个有用的答案.将性能视为活动的"类" - 每个都慢一个数量级(至少!):

  1. 仅访问CPU,内存使用量极少(即将非常简单的图形渲染到非常快的GPU,或计算Pi的数字)
  2. 只访问CPU和内存中的东西,磁盘上没有任何内容(即一个写得很好的游戏)
  3. 访问磁盘
  4. 访问网络.

如果你甚至做了第3项活动之一,那么对优化线程库的活动#1和#2进行优化是没有意义的 - 它们完全被磁盘命中所掩盖.CPU技巧也是如此 - 如果你经常发生L2/L3缓存未命中,通过手写程序集节省一些CPU周期是不值得的(这就是为什么像循环展开这样的事情这些天通常是个坏主意).

那么,我们可以从中得到什么呢?有两种方法可以让你的程序速度更快,无论是从#3拉升至#2(这是不是常常可能的,取决于你在做什么),或通过执行较少的I/O.I/O和网络速度是大多数现代应用程序中速率限制因素,就是您应该尝试优化的内容.

  • 使程序更快的另一种方法是以*更智能的方式执行IO.例如,对于传统的HDD,通常更快*不*并行执行IO,因为它会导致更多的搜索(这很慢). (7认同)
  • ^^这也是一个好主意.通过测量顺序读取的速度,测量读取磁盘上随机扇区的速度,然后比较方差,可以非常轻松地检测SSD.如果它们相似,那么你就有了SSD (4认同)
  • @svick我认为这是错误的,因为并行IO更快,因为使用SCAN和电梯算法实际上能够更好地安排读取 (3认同)

Ste*_*ary 22

面对"大量网络和磁盘I/O",这些选项之间的任何性能差异都是无关紧要的.

一个更好的问题是"哪个选项最容易学习和开发?" 或者"从现在起五年内哪个选项最好维护这段代码?" async如果您的逻辑更好地表示为流,那么我建议首先使用Dataflow或Rx.


Rob*_*žan 13

这是一个较老的问题,但对于读这篇文章的人来说......

这取决于.如果您尝试使用50B消息使1Gbps链路饱和,即使使用原始套接字进行简单的非阻塞发送,您也将受到CPU限制.另一方面,如果您对1Mbps吞吐量感到满意,或者您的消息大于10KB,那么任何这些框架都可以完成这项工作.

对于低带宽情况,我建议按易用性划分优先级,即async/await,Dataflow,Rx,TPL.请注意,高带宽应用程序应该原型化,就像它是低带宽并在以后优化一样.

对于真正的高带宽应用,我可以推荐基于Rx的Dataflow,因为Rx不是为高并发性而设计的.原始TPL是底层,如果您能够处理复杂性,它可以保证最低的开销.如果您可以有效地使用专用线程,那么这将更快.异步/等待与数据流IMO不会产生任何性能差异.开销似乎相当,所以选择一个更合适的开销.