[英]Execution time reactive programming
Is this an ideal way to find execution time of method ( getFavouriteDetails()
), in reactive programming ?这是在反应式编程中找到方法(
getFavouriteDetails()
)的执行时间的理想方法吗?
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()))
}
Two approaches to ensure that you only measure execution time when you subscribe -两种方法可确保您仅在订阅时测量执行时间 -
flatMapMany
.flatMapMany
将 Mono 包裹在 Flux flatMapMany
。 This returns a Flux as well.onSubscribe
and log elapsed time in doFinally
.onSubscribe
和日志经过时间的doFinally
。 Sample code -示例代码 -
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());
}
To time a method, the most basic way in Java is to use long System.nanoTime()
.要对方法计时,Java 中最基本的方法是使用
long System.nanoTime()
。 Instant
and System.currentTimeMillis
are for wall-clock operations and are not guaranteed to be monotonous nor precise enough... Instant
和System.currentTimeMillis
用于挂钟操作,不能保证单调或足够精确......
In Reactor, to measure the time a sequence takes to complete, you would usually need to start the timing on subscription (nothing happens until you subscribe) and stop the timing within a doFinally
(which execute some code on the side of the main sequence whenever it completes, errors or is cancelled).在 Reactor 中,要测量序列完成所需的时间,您通常需要在订阅时开始计时(在您订阅之前不会发生任何事情)并在
doFinally
停止计时(无论何时,它都会在主序列一侧执行一些代码它完成、出错或被取消)。
Here however you are subscribing yourself, so there is no risk to be multiple subscriptions.然而,在这里您是自己订阅的,因此没有多个订阅的风险。 You can thus do away with the "start timing on subscription" constraint.
因此,您可以取消“订阅开始时间”约束。
It gives us something like this:它给了我们这样的东西:
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!
}
Note that there is also a elapsed()
operator, which measures the time between subscription and 1st onNext, then between subsequent onNexts.请注意,还有一个
elapsed()
运算符,它测量订阅和第一个 onNext 之间的时间,然后是后续 onNexts 之间的时间。 It outputs a Flux<Tuple2<Long, T>>
, and you could aggregate the longs to get overall timing, but that would lose you the "realtime" nature of T
s in that case.它输出一个
Flux<Tuple2<Long, T>>
,你可以聚合 longs 以获得整体时间,但在这种情况下你会失去T
s的“实时”性质。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.