簡體   English   中英

執行時間響應式編程

[英]Execution time 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()))
}

兩種方法可確保您僅在訂閱時測量執行時間 -

  • 使用flatMapMany將 Mono 包裹在 Flux flatMapMany 這也返回一個 Flux 。
  • 使用的AtomicReference,設定時間在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());
}

要對方法計時,Java 中最基本的方法是使用long System.nanoTime() InstantSystem.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 之間的時間,然后是后續 onNexts 之間的時間。 它輸出一個Flux<Tuple2<Long, T>> ,你可以聚合 longs 以獲得整體時間,但在這種情況下你會失去T s的“實時”性質。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM