我试图证明RxJava与顺序(我假设的)阻塞计算相比的性能。
我在看this post和this SO question。根据经验,使用System.currentTimeMillis()和Thread.sleep()进行基准测试在处理计算而不是I / O时不会产生一致的结果,所以我尝试设置一个简单的JMH基准测试。
我的基准计算两个整数并将它们加起来:
public class MyBenchmark {
private Worker workerSequential;
private Worker workerParallel;
private int semiIntenseCalculation(int i) {
Double d = Math.tan(Math.atan(Math.tan(Math.atan(Math.tan(Math.tan(Math.atan(Math.tan(Math.atan(Math.tan(Math.atan(Math.tan(Math.tan(Math.atan(Math.tan(Math.atan(Math.tan(i)))))))))))))))));
return d.intValue() + i;
}
private int nonIntenseCalculation(int i) {
Double d = Math.tan(Math.atan(Math.tan(Math.atan(Math.tan(Math.tan(Math.atan(i)))))));
return d.intValue() + i;
}
private Observable<Object> intensiveObservable() {
return Observable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
int randomNumforSemi = ThreadLocalRandom.current().nextInt(0, 101);
Integer i = semiIntenseCalculation(randomNumforSemi);
int randomNumforNon = ThreadLocalRandom.current().nextInt(0, 101);
Integer j = nonIntenseCalculation(randomNumforNon);
return i+j;
}
});
};
private Observable<Object> semiIntensiveObservable() {
return Observable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
int randomNumforSemi = ThreadLocalRandom.current().nextInt(0, 101);
return semiIntenseCalculation(randomNumforSemi);
}
});
};
private Observable<Object> nonIntensiveObservable() {
return Observable.fromCallable(new Callable<Object>() {
@Override
public Object call() throws Exception {
int randomNumforNon = ThreadLocalRandom.current().nextInt(0, 101);
return nonIntenseCalculation(randomNumforNon);
}
});
};
public interface Worker {
void work();
}
@Setup
public void setup(final Blackhole bh) {
workerSequential = new Worker() {
@Override
public void work() {
Observable.just(intensiveObservable())
.subscribe(new Subscriber<Object>() {
@Override
public void onError(Throwable error) {
}
@Override
public void onCompleted() {
}
@Override
public void onNext(Object arg) {
bh.consume(arg);
}
});
}
};
workerParallel = new Worker() {
@Override
public void work() {
Observable.zip(semiIntensiveObservable().subscribeOn(Schedulers.computation()),
nonIntensiveObservable().subscribeOn(Schedulers.computation()),
new Func2<Object, Object, Object>() {
@Override
public Object call(Object semiIntensive, Object nonIntensive) {
return (Integer)semiIntensive + (Integer)nonIntensive;
}
}).subscribe(bh::consume);
}
};
}
@Benchmark
public void calculateSequential() {
workerSequential.work();
}
@Benchmark
public void calculateParallel() {
workerParallel.work();
}
}
我对结果感到困惑:
# Run complete. Total time: 00:00:21
Benchmark Mode Cnt Score Error Units
MyBenchmark.calculateParallel avgt 5 15602,176 ± 1663,650 ns/op
MyBenchmark.calculateSequential avgt 5 288,128 ± 6,982 ns/op
显然我期待并行计算更快。 RxJava是否仅适用于并行I / O或为什么我会得到这些结果?
答案 0 :(得分:1)
你做错了基准测试。您应该等待并行工作完成(否则通过blockingSubscribe
),您将启动相当多的工作,这会增加显着的GC开销并且还会使执行程序的内部队列膨胀。
Here是衡量各种并行工作的参考基准。请注意,调度工作本身就有开销,除非在并行设置中每个工作项有500个周期,否则您可能看不到这种fork-join类型并行工作负载的任何改进。