简体   繁体   English

执行时间响应式编程

[英]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 -两种方法可确保您仅在订阅时测量执行时间 -

  • Wrap a Mono around the Flux using flatMapMany .使用flatMapMany将 Mono 包裹在 Flux flatMapMany This returns a Flux as well.这也返回一个 Flux 。
  • Use an AtomicReference, set time in onSubscribe and log elapsed time in doFinally .使用的AtomicReference,设定时间在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... InstantSystem.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.

相关问题 面向方面的程序分析执行时间 - Aspect Oriented Programming profiling execution time Spring Framework WebFlux 响应式编程 - Spring Framework WebFlux Reactive Programming Spring Reactive Programming - “监听”数据存储区的更改 - Spring Reactive Programming - “Listen” to changes on datastore 反应式编程如何实现相关结果 - Reactive programming how to implement dependent result Spring 反应式编程和关系数据库:使用关系 - Spring reactive programming and relational databases: using relationships 使用 Mono 和 vanilla Java 编程的反应式编程之间的区别? - Difference between Reactive programming using Mono and vanilla Java programming? 如何使用 DB2 数据库实现反应式 Java 编程 - How to implement reactive Java programming with DB2 database 从列表创建助焊剂是否是针对反应式编程的优化解决方案? - Is creating flux from a list an optimized solution for reactive programming? 在反应式编程中如何优雅地关闭数据库连接池中的连接 - In reactive programming how to elegantly close the connection in the database connection pool Web反应式编程 - 从HTTP客户端的角度来看,有哪些优势? - Web Reactive Programming - What are the advantages from the HTTP client point of view?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM