java - java平台下如何测量上下文切换所花费的时间

标签 java multithreading testing

假设每个线程都在做一些 FP 计算,我有兴趣

  • CPU 用于切换线程而不是运行线程的时间
  • 在共享内存总线上创建了多少同步流量 - 当线程共享数据时,它们必须使用同步机制

我的问题:如何设计一个测试程序来获取这些数据?

最佳答案

您无法轻松区分线程切换和内存缓存争用造成的浪费。您可以测量线程争用。也就是说,在 linux 上,您可以 cat/proc/PID/XXX 并获得大量详细的每个线程统计信息。但是,由于抢先式调度程序不会让自己陷入困境,因此无论您使用多少线程,您每秒都不会得到超过 30 次 ctx 开关......而且那个时间将是相对的小vs你正在做的工作量。上下文切换的真正成本是缓存污染。例如一旦您重新切换回上下文,您很可能会出现大部分缓存未命中。因此,操作系统时间和上下文切换计数的值(value)很小。

真正有值(value)的是线程间缓存线脏的比率。根据 CPU 的不同,对等 CPU 读取之后的缓存线脏比缓存未命中要慢 - 因为您必须强制对等 CPU 将其值写入主内存,然后才能开始读取。. 一些CPU 可让您从对等缓存行中提取而无需访问 main-mem。

所以关键是绝对最小化任何共享的修改内存结构.. 使所有内容尽可能只读.. 这包括共享 FIFO 缓冲区(包括执行程序池).. 即如果您使用同步队列 - 那么每次同步-op 是一个共享的脏内存区域。而且,如果速率足够高,它可能会触发操作系统陷阱停止,等待对等线程的互斥体。

理想的做法是对 RAM 进行分段,将一个大型工作单元分配给固定数量的工作人员,然后使用倒计时锁存器或其他一些内存屏障(这样每个线程只会接触一次)。理想情况下,任何临时缓冲区都是预先分配的,而不是进出共享内存池(这会导致缓存争用)。 Java“同步” block 利用(在幕后)共享哈希表内存空间,从而触发不受欢迎的脏读,我还没有确定 java 5 Lock 对象是否避免了这种情况,但你仍然在利用操作系统停顿赢得了对您的吞吐量没有帮助。显然,大多数 OutputStream 操作都会触发此类同步调用(当然通常会填充公共(public)流缓冲区)。

一般来说,我的经验是,对于常见的字节数组/对象数组等而言,单线程比多线程更快。至少对于我尝试过的简单排序/过滤算法而言。根据我的经验,这在 Java 和 C 中都是如此。我没有尝试过 FPU 集成操作(如除法、sqrt),其中缓存行可能不是一个因素。

基本上,如果您是单个 CPU,则不会出现缓存线问题(除非操作系统总是在共享线程中刷新缓存),但多线程可以为您带来 yield 。在超线程中,情况相同。在单 CPU 共享 L2/L3 缓存配置(例如 AMD)中,您可能会发现一些好处。在多 CPU Intel BUS 中,算了吧——共享写内存比单线程更糟糕。

关于java - java平台下如何测量上下文切换所花费的时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6987394/

相关文章:

java - 拆箱问题

java - 我似乎无法在此打印程序中找到问题

java - 出于测试目的终止 Java 线程

c++ - 多线程文件读取每个线程产生相同的结果

c# - UI繁忙时更改光标

.net - 如何减少 .NET 中的 MSTest 执行时间?

java - 在启动时加载单选按钮选择

testing - 在 SBT 中运行测试而不编译 - 操作方法

java - 带有 Spring-boot stub 的 Spock 无法正常工作

java - 通过在 URL 中指定方法路由到特定的 HTTP 方法资源