jsr370-experts@jax-rs-spec.java.net

Default ExecutorService used on the client

From: Pavel Bucek <pavel.bucek_at_oracle.com>
Date: Fri, 28 Apr 2017 00:48:25 +0200

Dear EG members,

when settable executor service on the client side was introduced in the
API, there was also a default one specified - ManagedExecutorService
when running on the Java EE container and ForkJoinPool.commonPool() when
running on Java SE.

The latter seems to be little problematic.

We already have this implemented in Jersey and we noticed significant
performance drop in some type of tests. After some investigation, it is
caused by the ForkJoinPool.commonPool size. The default one is something
like 2x number of cores, which might not be enough for multiple reactive
invocations, not to mention that this pool is used by default by any
CompletionStage/CompletableFuture, parallel streams and other Java SE
classes/features, which makes the client performance not predictable and
very much dependent on the actual environment.

The obvious fix for these cases is to set ExecutorService for the
client, but it seems like that would be almost required (if we keep
commonPool as a default) for some usecases.

Another reason why we might want to change this is that
ForkJoinPool.commonPool seem to be mean for cpu intensive tasks and
JAX-RS client is using these threads for I/O - which is generally not
that much about CPU time. (just a summary: JAX-RS client is using that
for async and reactive calls as well as for SseEventSource).

What do you think about this issue? Should we lift the requirement to
use ForkJoinPool.commonPool as a default one? Or should we rather
highlight that fact in the documentation and examples and make super
clear that using custom executor service is strongly suggested for
advanced usecases?

Thanks and regards,
Pavel