Pra*_*era 17 java multithreading
很多时候我听说最好将线程池中的线程数保持在该系统中的核心数之下.拥有两个或更多线程而不是内核数量不仅是浪费,而且还可能导致性能下降.
那些是真的吗?如果没有,那些揭穿这些主张(特别是与java有关)的基本原则是什么?
Ste*_*n C 24
这些说法不是一般性声明.也就是说,有时候它们是真的(或者是真实的),有时它们是明显错误的.
有几件事无疑是真的:
更多线程意味着更多内存使用.每个线程都需要一个线程堆栈.对于最近的HotSpot JVM,最小线程堆栈大小为64Kb,默认值可以高达1Mb.这可能很重要.此外,任何活动的线程都可能拥有或共享堆中的对象,无论它是否当前是可运行的.因此,期望更多线程意味着更大的内存工作集是合理的.
与执行硬件上的内核(或超线程内核或其他内容)相比,JVM实际上不能运行更多线程.如果没有引擎,汽车将无法运行,如果没有核心,线程将无法运行.
除此之外,事情变得不那么明确."问题"是活动线程可以处于各种"状态".例如:
"每个核心一个线程"启发式假定线程正在运行或可运行(根据上述内容).但是对于很多多线程应用程序来说,启发式是错误的......因为它没有考虑其他状态中的线程.
现在"太多"线程显然会导致显着的性能下降,使用太多内存很简单.(想象一下,你拥有4Gb的物理内存,你可以用1Mb堆栈创建8,000个线程.这是虚拟内存抖动的一个秘诀.)
但其他事情呢?有太多线程会导致过多的上下文切换吗?
我不这么认为.如果你有大量的线程,和你的应用程序使用的线程可能会导致过多的上下文切换,这是不好的性能.但是,我认为上下文切换的根本原因不是实际的线程数.性能问题的根源更可能是应用程序:
Object.notifyAll()何时Object.notify()会更好,或者(在最后一种情况下,瓶颈可能是I/O系统而不是上下文切换......除非I/O是IPC与同一台机器上的服务/程序.)
另一点是,在没有上述混淆因素的情况下,拥有更多线程不会增加上下文切换.如果你的应用程序有N个可运行的线程竞争M个处理器,并且线程纯粹是计算和无争用的,那么OS的线程调度程序将尝试在它们之间进行时间分片.但是,时间片的长度很可能以十分之一秒(或更长)来测量,因此与CPU绑定线程在其切片期间实际执行的工作相比,上下文切换开销可以忽略不计.如果我们假设时间片的长度是常数,那么上下文切换开销也将是恒定的.添加更多可运行的线程(增加N)不会显着改变工作与开销的比率.
总之,"太多线程"确实对性能有害.然而,对于有多少"太多",没有可靠的通用"经验法则".并且(幸运的是)在"太多"的性能问题变得显着之前,您通常有相当大的余地.
这不是真的,除非线程数量远远多于核心数量。原因是额外的线程将意味着额外的上下文切换。但这不是真的,因为操作系统只会在这些上下文切换有益的情况下才会进行非强制上下文切换,并且附加线程不会强制附加上下文切换。
如果创建的线程数量过多,就会浪费资源。但与创建太少线程的糟糕程度相比,这一切都不算什么。如果创建的线程太少,意外的块(例如页面错误)可能会导致 CPU 闲置,从而消除了一些额外的上下文切换可能造成的损害。
线程数少于核心数通常意味着您无法利用所有可用内核.
通常的问题是你想要的核心数多于核心数.但是,这会有所不同,具体取决于线程花费在I/O上的时间(总体)与执行计算所花费的时间.如果他们都在进行纯计算,那么您通常需要与核心数相同的线程数.如果他们做了相当多的I/O,你通常需要比核心更多的线程.
从另一个方向看一下,你需要运行足够多的线程来确保每当一个线程由于某种原因阻塞(通常在I/O上等待)时,你可以在该核心上运行另一个线程(没有阻塞).确切的数字取决于每个线程花费多少时间被阻止.
| 归档时间: |
|
| 查看次数: |
12187 次 |
| 最近记录: |