我有一段 C# 5.0 代码可以生成大量的网络和磁盘 I/O。我需要并行运行此代码的多个副本。以下哪项技术可能会给我带来最佳性能:
带有等待的异步方法
直接使用 TPL 中的 Task
TPL 数据流 nuget
反应式扩展
我不太擅长这种并行的东西,但是如果使用较低的杠杆,比如 Thread,可以给我更好的性能,我也会考虑这一点。
我有一段 C# 5.0 代码可以生成大量的网络和磁盘 I/O。我需要并行运行此代码的多个副本。以下哪项技术可能会给我带来最佳性能:
带有等待的异步方法
直接使用 TPL 中的 Task
TPL 数据流 nuget
反应式扩展
我不太擅长这种并行的东西,但是如果使用较低的杠杆,比如 Thread,可以给我更好的性能,我也会考虑这一点。
这就像试图通过询问最快的方法来解开安全带来优化跨大西洋飞行的长度。
让我们给出一个有用的答案。将性能视为活动的“类” - 每个活动都慢一个数量级(至少!):
如果您甚至执行活动 #3 中的一项,那么进行活动 #1 和 #2 的典型优化(例如优化线程库)毫无意义——它们完全被磁盘命中所掩盖。CPU 技巧也是如此 - 如果您经常发生 L2/L3 缓存未命中,那么通过手写汇编节省几个 CPU 周期是不值得的(这就是为什么如今循环展开之类的事情通常是个坏主意)。
那么,我们可以从中得到什么?有两种方法可以让你的程序更快,或者从 #3 提升到 #2(这通常是不可能的,这取决于你在做什么),或者减少 I/O。I/O 和网络速度是大多数现代应用程序中的速率限制因素,这就是您应该尝试优化的因素。
面对“大量的网络和磁盘 I/O”,这些选项之间的任何性能差异都将是无关紧要的。
一个更好的问题是“哪个选项最容易学习和开发?” 或者“从现在起五年内维护此代码的最佳选择是什么?” 为此,如果您的逻辑更好地表示为流,我建议async
首先使用 Dataflow 或 Rx。
这是一个较老的问题,但是对于阅读此书的任何人...
这取决于。如果您尝试使用 50B 消息使 1Gbps 链路饱和,即使通过原始套接字进行简单的非阻塞发送,您也会受到 CPU 的限制。另一方面,如果您对 1Mbps 的吞吐量感到满意,或者您的消息大于 10KB,那么这些框架中的任何一个都可以完成这项工作。
对于低带宽的情况,我建议按易用性优先,即按此顺序排列异步/等待、Dataflow、Rx、TPL。请注意,高带宽应用程序应该像低带宽应用程序一样进行原型设计,并在以后进行优化。
对于真正的高带宽应用程序,我可以推荐 Dataflow over Rx,因为 Rx 不是为高并发设计的。原始 TPL 是底层,如果您可以处理复杂性,它可以保证最低的开销。如果您可以有效地使用专用线程,那将会更快。Async/await 与 Dataflow IMO 没有任何性能差异。开销似乎相当,所以选择一个更合适的。