这是在反应式编程中查找方法(getFavourites)执行时间的理想方法吗?
public List<Favourites> getFavouriteDetails(String userId){
userService.getFavorites(userId)
.flatMap(favoriteService::getDetails)
.switchIfEmpty(suggestionService.getSuggestions())
.take(5)
.publishOn(UiUtils.uiThreadScheduler())
.subscribe(uiList::show, UiUtils::errorPopup)
.flatMap(a -> Mono.subscriberContext().map(ctx -> {
log.info("Time taken : " + Duration.between(ctx.get(key), Instant.now()).toMillis() + " milliseconds.");
return a;
}))
.subscriberContext(ctx -> ctx.put(key, Instant.now()))
}
答案 0 :(得分:3)
两种方法可确保仅在订阅时衡量执行时间-
flatMapMany
将Mono环绕在助焊剂上。这也会返回磁通量。onSubscribe
中设置时间,并在doFinally
中记录经过的时间。示例代码-
timeFluxV1(getFavouriteDetails(userId)).subscribe(uiList::show, UiUtils::errorPopup);
timeFluxV1(getFavouriteDetails(userId)).subscribe(uiList::show, UiUtils::errorPopup);
private <T> Flux<T> timeFluxV1(Flux<T> flux) {
return Mono.fromSupplier(System::nanoTime)
.flatMapMany(time -> flux.doFinally(sig -> log.info("Time taken : " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - time) + " milliseconds.")));
}
private <T> Flux<T> timeFluxV2(Flux<T> flux) {
AtomicReference<Long> startTime = new AtomicReference<>();
return flux.doOnSubscribe(x -> startTime.set(System.nanoTime()))
.doFinally(x -> log.info("Time taken : " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime.get()) + " milliseconds."));
}
public Flux<Favourites> getFavouriteDetails(String userId) {
return userService.getFavorites(userId)
.flatMap(favoriteService::getDetails)
.switchIfEmpty(suggestionService.getSuggestions())
.take(5)
.publishOn(UiUtils.uiThreadScheduler());
}
答案 1 :(得分:1)
要计时某个方法,Java中最基本的方法是使用long System.nanoTime()
。 Instant
和System.currentTimeMillis
用于壁钟操作,不保证其单调或不够精确...
在Reactor中,要测量一个序列完成所花费的时间,通常需要启动订阅计时(直到您订阅之前什么都不会发生),并在doFinally
(在其中执行一些代码)内停止计时主序列的一侧,只要它完成,出错或被取消)。
但是,这里您要订阅自己,因此不存在多个订阅的风险。因此,您可以消除“订阅开始时间”约束。
它给我们这样的东西:
public List<Favourites> getFavouriteDetails(String userId){
final long start = System.nanoTime();
userService.getFavorites(userId)
.flatMap(favoriteService::getDetails)
.switchIfEmpty(suggestionService.getSuggestions())
.take(5)
.publishOn(UiUtils.uiThreadScheduler())
.doFinally(endType -> log.info("Time taken : " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start) + " milliseconds."))
.subscribe(uiList::show, UiUtils::errorPopup);
//return needed!
}
请注意,还有一个elapsed()
运算符,用于测量预订与第一个onNext之间以及随后的onNext之间的时间。它输出一个Flux<Tuple2<Long, T>>
,您可以汇总多头以获得总体时间,但是在这种情况下,这将使您失去T
的“实时”性质。