reactor-core icon indicating copy to clipboard operation
reactor-core copied to clipboard

Eager vs Lazy prefetch

Open bsideup opened this issue 5 years ago • 2 comments

In current version of Reactor ( 3.2.1.RELEASE ), this code will do request(100) (because of eager prefetch):

Flux.range(0, Integer.MAX_VALUE)
        .hide()
        .log("producer")
        .concatMap(Mono::just, 100)
        .log("subscriber")
        .subscribe(new Subscriber<>() {
            @Override
            public void onSubscribe(Subscription s) {
            }

            @Override
            public void onNext(Integer integer) {

            }

            @Override
            public void onError(Throwable t) {

            }

            @Override
            public void onComplete() {

            }
        });

// 11:25:40.166  INFO   --- producer   : onSubscribe(FluxHide.HideSubscriber)
// 11:25:40.182  INFO   --- subscriber : onSubscribe(FluxConcatMap.ConcatMapImmediate)
// 11:25:40.184  INFO   --- producer   : request(100)

Suggestion: Optional prefetch mode, LAZY|EAGER. If it is LAZY, there will be no prefetch unless downstream does it's first request.

Motivation: While it's ok for most of use cases, it might be a big issue when the publisher is some IO source (e.g. Kafka, RSocket, etc), where requesting before the subscriber is ready to consume is a waste of resources and might affect the startup time of the app if there are some global publishers (e.g. message processing)

bsideup avatar Oct 22 '18 09:10 bsideup

FTR while #2202 does not fix it, it at least provides a workaround (no prefetch mode)

bsideup avatar Jul 06 '20 13:07 bsideup

Keeping this issue (on-hold) to track possible research into different request tradeoffs in a 4.0.0

Prefetching was a tradeoff that was made at project inception, which is hard to change now. As soon as 1-to-N operators like concatMap or flatMap are used, prefetching compounds with request re-patterning these operators necessarily do and the upstream request patterns become less predictable. That's the tradeoff, in exchange for better performance without tuning.

Perhaps a different tradeoff would be made today (predictability of requests upstream, lifecycle management with deeper integration of discarding, ...) but that's such a deep change, it would effectively represent a fourth generation of Reactor.

simonbasle avatar Feb 18 '21 09:02 simonbasle