Интересно было узнать о возможностях CompletableFeature.
Проект и описание находится тут https://github.com/cherepakhin/completablefeature_many_benchmark
ExecutorService executorService = Executors.newCachedThreadPool();
String getContext() {
return StringUtils.repeat("-", 1000);
}
// Имитация работы какого-то внешнего сервиса
void sleep() {
try {
TimeUnit.MILLISECONDS.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@GetMapping("/")
public String trivial() {
sleep();
return getContext();
}
@GetMapping("/simple")
public CompletableFuture simple() {
return CompletableFuture.supplyAsync(() -> {
sleep();
return getContext();
}, executorService);
}
@GetMapping("/nested")
public CompletableFuture nested() {
return CompletableFuture.supplyAsync(() -> {
return CompletableFuture.supplyAsync(() -> {
sleep();
return getContext();
},executorService
);
},executorService).get();
}
Ниже описаны только итоги.
Нагрузка во всех вариантах 500rps
| Схема кэширования | Среднее время ответа (мс) | К-во тредов (шт) | Память (Мб) |
| Без CompletableFeature | 5 000 | 229 | 150 |
| С CompletableFeature Executors.newCachedThreadPool() | 1 000 | 847 | ~230 |
| Кол-во выделяемых сервисом тредов меньше нагрузки (нагрузка 500 rps, а тредов выделено 100) . CompletableFeature executorService = Executors.newFixedThreadPool(100) | >10 000 | 188 | 200-350 |
С CompletableFeature время ответа сократилось аж в 5 раз! Но, увеличился расход памяти. Неоднозначные результаты в третьей строке (Кол-во выделяемых сервисом тредов меньше нагрузки).
И все таки насколько ценен CompletableFeature? Какую проблему мы решаем, используя это решение? Может быть лучшие результаты даст кеш или оптимизация самих сервисов? По своему опыту скажу, что разработка, тестирование с CompletableFeature, мягко говоря, имеет свою специфику. Возвращая CompletableFeature в методе, вы принуждаете клиента его обрабатывать и перекладывете проблему дальше, и кому-то все-равно придется ее разрулить. Если уж решили использовать CompletableFeature, то сам его тут же и разруливай. Грубо говоря, это локальное(техническое) решение, на уровне приватных методов класса. Не должно путаться в бизнес логике. Остальные классы не должны быть замешаны в эту кашу. Еще большие сомнения, использование CompletableFeature в Spring окружении, т.к. Spring сам решает эту проблему.
O CompletableFeature
https://www.baeldung.com/java-completablefuture