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.

Honestly I think both are almost identical, just different styles to write it. In fact, the flatMap IIRC under the covers is a merge operation. I’d prefer the first snippet since its more compact and doesn’t require you to create an additional list for no real benefit

1 Like