简体   繁体   中英

Performance reduction when using DeferredResult and RxJava with Spring MVC

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

After playing around further, it seems the main issue I was encountering was that the delay I chose (~20ms) was too small to take advantage of asynchronous operations in Spring MVC + RxJava. Increasing to ~500ms did the trick and showed big performance improvements.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM