Search code examples
javaperformancerx-javacouchbasecouchbase-java-api

Couchbase RX Client - Merging multiple observables vs flatmap


What is the performance difference between the following code snippets?

Use case: retrieve multiple keys from Couchbase using the Couchbase reactive SDK.

Snippet #1

 return Observable
            .from(keys)
            .flatMap(id ->
                    bucket.get(id, RawJsonDocument.class)
            )
            .toList()
            .toBlocking()
            .single();

Snippet #2

     List<Observable<RawJsonDocument>> list = new ArrayList<>();
     keys.forEach(key -> list.add(bucket.get(key, RawJsonDocument.class)));
     return Observable.merge(list)
            .toList()
            .toBlocking()
            .single();

The first snippet is the recommended way according to CB's documentation.

Also, at the very end the observable is converted into a blocking one, but everything before that, including the network calls and the aggregation, is happening completely asynchronously.

Inside the SDK, this provides much more efficient resource utilization because the requests are very quickly stored in the internal Request RingBuffer and the I/O threads are able to pick batches as large as they can. Afterward, whatever server returns a result first it is stored in the list, so there is no serialization of responses going on.

The second snippet is a case we found in our codebase today, where there's a list of Observables, where each observable triggers a get method of Bucket one by one and then merges them all.


Solution

  • There should be no performance difference between the two snippets, from the perspective both of the Couchbase SDK and RxJava, they are very similar (as flatMap basically do a map to Observables like your keys.forEach, then merge the observables in a loop).

    edit: from a personal perspective I still prefer the first style though ;)