【发布时间】:2013-10-08 17:36:00
【问题描述】:
我想我不完全了解 scalaz Futures 的工作原理。我正在尝试将一个项目从 scala futures 移植到 scalaz 实现,但问题是 scalaz Future 的性能较低。最简单的示例是使用 Spray 在身份验证请求中加载配置文件。
函数本身:
def loadProfile[A: CollectionProvider: JsonFormat](id: String) = future {
remote.findOne[A]("id" :> id) match {
case Some(profile) ⇒ \/-(profile)
case None ⇒ -\/(ProfileNotFoundRejection(id))
}
}
scalaz 版本仅在一个符号上有所不同,我从scalaz.concurrent 调用Future.apply。
现在加载一些 html 页面的 Spray 路由:
get {
path("profile" / "id" ~ Segment) { id ⇒
onSuccess(loadProfile[User](id)) {
case \/-(profile) ⇒ complete(html.page(profile))
case -\/(pnfr) ⇒ reject(pnfr)
}
}
}
与loadProfile 一样,scalaz 版本的不同之处仅在于方法调用:
get {
path("profile" / "id" ~ Segment) { id ⇒
ctx => loadProfile[User](id).runAsync {
case \/-(profile) ⇒ ctx.complete(html.page(profile))
case -\/(pnfr) ⇒ ctx.reject(pnfr)
}
}
}
但是 scala Future 版本的请求在(大约)143ms 内完成,而 scalaz 版本在 260ms 内完成。所以我不太关心这个特定的请求,而是一般的异步执行和服务的可扩展性,正如我在scalaz Future中理解的那样,我必须手动将执行分叉到一个单独的线程,所以它按顺序执行? scalaz 未来的用法有什么好的介绍/教程吗?
【问题讨论】:
-
抱歉,按返回太快了。也许它与用于执行计算的底层 ExecutorService 有关? Scalaz 的
Future.apply将 ExecutorService 作为隐式参数。默认情况下,它使用ExecutorService.newFixedThreadPool(...),使用您机器上可用的处理器数量。在 Spray 路由中创建的Futures 默认使用 Akka 调度程序,这是一个 Fork-Join 池。
标签: scala asynchronous future scalaz spray