I've been trying to experiment with the possible performance implications of integrating DeferredResult and RxJava with Spring MVC. Notice the decrease in performance from the norx endpoint compared to the rx endpoints. I was expecting the RxJava + DeferredResult implementation to outperform (# of requests, req/sec) the vanilla one. Can anyone explain why this happened?
Using the following code: https://gist.github.com/richardkabiling/b53eae46c4414d4341ef310bf3a070c1
@Controller
public class SumController {
SecureRandom random = new SecureRandom();
@RequestMapping(value = "/init")
public ResponseEntity<Void> init() {
return ResponseEntity.ok(null);
}
@RequestMapping(value = "/norx1")
public ResponseEntity<BigDecimal> simpleSync() {
return ResponseEntity.ok(getA());
}
@RequestMapping(value = "/rx1")
public DeferredResult<ResponseEntity<BigDecimal>> simpleAsync() {
DeferredResult<ResponseEntity<BigDecimal>> result = new DeferredResult<>();
Observable.create(emit(this::getA))
.map(n -> ResponseEntity.ok(n))
.subscribe(re -> result.setResult(re));
return result;
}
@RequestMapping(value = "/norx2")
public ResponseEntity<BigDecimal> sync() {
return ResponseEntity.ok(getA().add(getB()));
}
@RequestMapping(value = "/rx2")
public DeferredResult<ResponseEntity<BigDecimal>> async() {
DeferredResult<ResponseEntity<BigDecimal>> result = new DeferredResult<>();
Observable.create(emit(this::getA))
.zipWith(Observable.create(emit(this::getB)), (x, y) -> x.add(y))
.map(n -> ResponseEntity.ok(n))
.subscribe(re -> result.setResult(re));
return result;
}
private Observable.OnSubscribe<BigDecimal> emit(Supplier<? extends BigDecimal> p) {
return s -> {
s.onNext(p.get());
s.onCompleted();
};
}
private BigDecimal getA() {
sleep();
return BigDecimal.valueOf(500);
}
private BigDecimal getB() {
sleep();
return BigDecimal.valueOf(300);
}
private void sleep() {
try { Thread.sleep(10 + random.nextInt(10)); } catch (InterruptedException e) { }
}
}
I got the following performance results (using wrk
):
Running 10s test @ http://localhost:8080/norx1
10 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 78.11ms 31.32ms 250.18ms 67.27%
Req/Sec 307.06 68.75 474.00 65.60%
30663 requests in 10.05s, 4.98MB read
Socket errors: connect 759, read 129, write 0, timeout 0
Requests/sec: 3052.35
Transfer/sec: 507.18KB
Running 10s test @ http://localhost:8080/rx1
10 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 86.67ms 38.32ms 313.65ms 67.19%
Req/Sec 277.84 101.59 565.00 73.37%
27732 requests in 10.08s, 4.50MB read
Socket errors: connect 759, read 0, write 0, timeout 0
Requests/sec: 2749.94
Transfer/sec: 456.98KB
Running 10s test @ http://localhost:8080/norx2
10 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 77.19ms 21.17ms 224.72ms 67.65%
Req/Sec 311.54 174.18 770.00 68.80%
31115 requests in 10.09s, 5.05MB read
Socket errors: connect 759, read 116, write 0, timeout 0
Requests/sec: 3084.71
Transfer/sec: 512.57KB
Running 10s test @ http://localhost:8080/rx2
10 threads and 1000 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 86.05ms 27.78ms 226.40ms 64.60%
Req/Sec 554.96 387.63 1.28k 55.13%
27761 requests in 10.07s, 4.51MB read
Socket errors: connect 759, read 102, write 0, timeout 0
Requests/sec: 2756.15
Transfer/sec: 458.01KB