用开始时间和结束时间包装 monix 任务的最佳方法是什么?



这就是我现在正在尝试的,但它只打印"嘿"而不是指标。 我不想在主函数中添加与指标相关的东西。

import java.util.Date
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import scala.concurrent.Await
import scala.concurrent.duration.Duration
class A {
def fellow(): Task[Unit] = {
val result = Task {
println("hey")
Thread.sleep(1000)
}
result
}
}
trait AA extends A {
override def fellow(): Task[Unit] = {
println("AA")
val result = super.fellow()
val start = new Date()
result.foreach(e => {
println("AA", new Date().getTime - start.getTime)
})
result
}
}
val a = new A with AA
val res: Task[Unit] = a.fellow()
Await.result(res.runAsync, Duration.Inf)

您可以描述如下函数:

def measure[A](task: Task[A], logMillis: Long => Task[Unit]): Task[A] =
Task.deferAction { sc =>
val start = sc.clockMonotonic(TimeUnit.MILLISECONDS)
val stopTimer = Task.suspend {
val end = sc.clockMonotonic(TimeUnit.MILLISECONDS)
logMillis(end - start)
}
task.redeemWith(
a => stopTimer.map(_ => a)
e => stopTimer.flatMap(_ => Task.raiseError(e))
)
}

一些建议:

  1. Task值应该是纯的,以及返回Tasks 的函数 — 触发副作用并在结果被破坏时返回Task的函数
    • Task不是Future的1:1替代品;在描述Task时,所有的副作用都应该暂停(包裹(在Task
    • foreach触发Task的评估,这不好,因为它触发了副作用;我正在考虑弃用和删除它,因为它的存在很诱人
  2. 停止使用特质继承,只使用普通函数——除非你深刻理解 OOP 和子类型,否则最好尽可能避免它;如果你喜欢 Cake 模式,停止这样做,也许加入一个支持小组 🙂
  3. 永远不要通过new Date()测量持续时间,你需要一个单调的时钟,并且在System.nanoTime的JVM之上,可以通过Monix的Scheduler访问clockMonotonic,如上所述,Scheduler通过deferAction
  4. 给你
  5. 停止阻塞线程,因为这容易出错 - 而不是做Thread.sleep,做Task.sleep,所有Await.result调用都是有问题的,除非它们在main或其他无法处理异步的地方

希望这有帮助。

干杯

就像@Pierre提到的,最新版本的Monix Task已经Task.timed,你可以做

timed <- task.timed
(duration, t) = timed

相关内容

  • 没有找到相关文章

最新更新