简单基准测试(Java)奇怪的多线程性能
最近,我编写了一个非常简单的代码作为基准,以查看我的机器性能的提高。它只是创建一些线程,并在这些线程之间划分一些旋转数。下面是我用java扩展线程的类:简单基准测试(Java)奇怪的多线程性能,java,multithreading,performance,benchmarking,Java,Multithreading,Performance,Benchmarking,最近,我编写了一个非常简单的代码作为基准,以查看我的机器性能的提高。它只是创建一些线程,并在这些线程之间划分一些旋转数。下面是我用java扩展线程的类: public static class LoopThread extends Thread { int index; long numberOfRound; long numberOfSpins; public LoopThread(int index, long numberOfRound, long num
public static class LoopThread extends Thread {
int index;
long numberOfRound;
long numberOfSpins;
public LoopThread(int index, long numberOfRound, long numberOfSpins) {
this.index = index;
this.numberOfRound = numberOfRound;
this.numberOfSpins = numberOfSpins;
}
public void run() {
System.out.println("Thread " + index + " started for " + numberOfRound + " rounds and " + numberOfSpins + " spins");
for(long i = 0; i < numberOfRound; i++) {
for(long j = 0; j < numberOfSpins; j++) {
}
}
System.out.println("Thread " + index + " ended");
}
这一变化使我的代码更具可伸缩性。由于我看不出这一变化导致这种改善的明显原因,我一次又一次地尝试,这里有一些我一直看到的结果:
更改前:
time passed for 8 threads and 1000000 rounds and 800000 spins is 63 seconds
time passed for 9 threads and 1000000 rounds and 800000 spins is 69 seconds
简单更改后:
time passed for 8 threads and 1000000 rounds and 800000 spins is 62 seconds
time passed for 9 threads and 1000000 rounds and 800000 spins is 56 seconds
再一次,我看不出这背后有什么明显的原因,我觉得这很奇怪。你知道为什么会这样吗
谢谢
编辑(启动线程和时间的代码):
publicstaticvoidmain(字符串[]args){
int numberOfThreads=Integer.parseInt(args[0]);
long numberOfRounds=long.parseLong(args[1]);
long numberOfSpins=long.parseLong(args[2]);
long startTime=System.currentTimeMillis();
线程[]线程=新线程[numberOfThreads];
for(int i=0;i
发布启动线程和任务完成时间的代码/方法。当然,请检查我的编辑。谢谢你的机器有超线程吗?你可能只有8个真正的CPU内核,所以你不会看到任何改进,过去8线程简单CPU绑定基准这样。是的,它有超线程,但我们看到几乎16X的改进与类似的C++基准与16个线程。另外,我看到在我提到的变更后,改进了14.5倍左右,之前是变更前的11倍左右。我不知道这个改变是如何产生一个更具可伸缩性的代码的。我真的不想深入到正确答案的细节,但我猜你看到的问题与JIT编译器有关,如果编译器完全优化了这个代码,它将需要0毫秒来运行,因为在循环中实际上什么都没有发生。显然,这并不完全是正在发生的事情,但要真正调查它,您应该使用JMH基准框架并启用调试,以查看JVM在每种情况下生成的机器代码。发布启动线程和任务完成时间的代码/方法。当然,请检查我的编辑。谢谢你的机器有超线程吗?你可能只有8个真正的CPU内核,所以你不会看到任何改进,过去8线程简单CPU绑定基准这样。是的,它有超线程,但我们看到几乎16X的改进与类似的C++基准与16个线程。另外,我看到在我提到的变更后,改进了14.5倍左右,之前是变更前的11倍左右。我不知道这个改变是如何产生一个更具可伸缩性的代码的。我真的不想深入到正确答案的细节,但我猜你看到的问题与JIT编译器有关,如果编译器完全优化了这个代码,它将需要0毫秒来运行,因为在循环中实际上什么都没有发生。显然,这并不完全是正在发生的事情,但要真正研究它,您应该使用JMH基准测试框架并启用调试来查看JVM在每种情况下生成的机器代码。
time passed for 8 threads and 1000000 rounds and 800000 spins is 62 seconds
time passed for 9 threads and 1000000 rounds and 800000 spins is 56 seconds
public static void main(String[] args) {
int numberOfThreads = Integer.parseInt(args[0]);
long numberOfRounds = Long.parseLong(args[1]);
long numberOfSpins = Long.parseLong(args[2]);
long startTime = System.currentTimeMillis();
Thread[] threads = new Thread[numberOfThreads];
for( int i = 0; i < numberOfThreads; i++) {
threads[i] = new LoopThread(i, numberOfRounds, (long) numberOfSpins/numberOfThreads);
threads[i].start();
}
for(Thread t: threads) {
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
long endTime = System.currentTimeMillis() - startTime;
System.out.println("time passed for " + numberOfThreads + " threads and " + numberOfRounds + " rounds and " + numberOfSpins + " spins is " + endTime/1000 + " seconds");
}