6

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

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)
4

2 回答 2

11

你可以这样描述一个函数:

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不是 1:1 的替代品Future;描述 a 时Task,所有副作用都应暂停(包装)在Task
    • foreach触发Task的评估,这不好,因为它会触发副作用;我正在考虑弃用和删除它,因为它的存在很诱人
  2. 停止使用 trait 继承,只使用普通函数——除非你深入了解 OOP 和子类型化,否则最好尽可能避免它;如果您喜欢蛋糕模式,请停止这样做并加入支持小组
  3. 从不通过 测量持续时间new Date(),您需要一个单调时钟,并且在 JVM 之上System.nanoTime,它可以通过 Monix 的Schedulerby访问clockMonotonic,如上例所示,Scheduler通过deferAction
  4. 停止阻塞线程,因为这很容易出错——而不是Thread.sleepdo , doTask.sleep和所有Await.result调用都是有问题的,除非它们在main或在其他无法处理异步的地方

希望这可以帮助。

干杯,

于 2018-06-22T09:58:58.257 回答
2

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

timed <- task.timed
(duration, t) = timed
于 2020-12-21T22:20:44.087 回答