我正在学习反应式编程技术,使用异步I / O等,而我无法找到关于不切换线程的好处的权威比较数据。
与计算相比,显然切换线程“昂贵”。但我们谈的是什么规模?
基本问题是“切换java线程需要多少个处理器周期/指令?” (我期待一个范围)
受OS影响吗? 我认为它受线程数量的影响,这就是为什么异步IO比阻塞好得多的原因 - 线程越多,上下文的存储距离就越远(大概甚至可以从缓存中进入主内存)。
我见过Approximate timings for various operations虽然它(方式)已经过时,但对于处理器周期的关联可能仍然有用(网络可能需要更多“指令”,SSD磁盘可能更少)。 / em>的
据我所知,反应式应用程序使网络应用程序的速度从每秒1000次增加到10,000次(每台服务器),但这也很难说 - 欢迎评论
注意 - 我知道这是一个模糊,无用,蓬松的问题,因为我对影响上下文切换速度的输入知之甚少。也许统计答案会有所帮助 - 例如我猜测> = 60%的线程需要100-10000个处理器周期才能切换。
答案 0 :(得分:1)
Rugal有一个观点。在现代架构中,理论周转时间通常远离实际测量,因为硬件以及软件变得如此复杂。它本身也取决于您的应用程序。例如,许多Web应用程序都受I / O约束,而上下文切换时间的重要性要低得多。
另请注意,context switching(您称之为线程切换)是操作系统的东西而不是Java的东西。无法保证操作系统中的上下文切换“重”。过去需要花费数十甚至数十万个CPU周期来进行kernel-level switch,但也有user-level switches以及实验系统,甚至内核级交换机也只需要几百个周期。
答案 1 :(得分:0)
线程切换是由OS完成的,因此Java与它无关。另外,至少在linux上,但我还假定许多其他操作系统,调度成本不取决于线程数。从2.6版开始,Linux一直使用O(1)调度程序。
Linux上的线程切换开销为some 1.2 µs(来自2018年的文章)。不幸的是,本文没有列出测量的时钟速度,但是开销应该是1000-2000个时钟周期左右。在给定的机器和OS上,线程切换开销应该或多或少是恒定的,而不是一个大范围。
除了这种直接切换成本之外,还存在更改工作负载的成本:新线程很可能使用一组不同的指令和数据,需要将它们加载到缓存中,但是在不同线程之间,此成本没有区别。线程切换或异步编程的“上下文切换”。为了完整起见,切换到完全不同的进程会增加更改内存地址空间的额外开销,这也很重要。
相比之下,Go编程语言(使用与异步编程技术非常相似的用户空间线程)中的goroutines之间的切换开销约为170 ns,因此占Linux线程切换的七分之一。
这是否对您有意义,当然取决于您的用例。但是对于大多数任务,您花费在计算上的时间将远远超过上下文切换的开销。除非您有很多线程在切换之前做绝对很少的工作。
自2000年代初以来,线程开销已大大改善,并且根据链接的文章,在具有大量内存的最新服务器上,在生产环境中运行10,000个线程应该不是问题。线程切换速度慢的一般说法通常是基于过去的计算机,因此,请谨慎考虑。
异步编程的另一个基本优点是用户空间调度程序对任务有更多的了解,因此原则上可以做出更明智的调度决策。它也不必处理来自不同用户的流程,这些流程所执行的工作大不相同,而仍然需要公平地计划。但是即使这样也可以解决,并且使用正确的内核扩展these Google engineers可以将线程切换开销减少到与goroutine切换相同的范围(200 ns)。