le-*_*ude 5 java jvm scala playframework playframework-2.1
我知道如何创建自己的ExecutionContext或导入play框架全局.但我必须承认,我远不是一个关于多个上下文/执行服务如何在后面工作的专家.
所以我的问题是,为了我的服务的性能/行为更好,我应该使用ExecutionContext?
我测试了两个选项:
import play.api.libs.concurrent.Execution.defaultContext
Run Code Online (Sandbox Code Playgroud)
和
implicit val executionContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()))
Run Code Online (Sandbox Code Playgroud)
两者都带来了可比的表现.
我使用的操作在playframework 2.1.x中实现如下.SedisPool是我自己的对象,带有额外的Future包装正常的sedis/jedis客户端池.
def testaction(application: String, platform: String) = Action {
Async(
SedisPool.withAsyncClient[Result] { client =>
client.get(StringBuilder.newBuilder.append(application).append('-').append(platform).toString) match {
case Some(x) => Ok(x)
case None => Results.NoContent
}
})
}
Run Code Online (Sandbox Code Playgroud)
这个性能wize的行为与Node.js和Go中完全相同的函数一样好或稍慢.但仍然比Pypy慢.但是比Java更快(在这种情况下使用jedis使用阻塞调用redis).我们用加特林进行了测试.我们正在对redis之上的简单服务进行技术"竞争",标准是"与编码员一样努力".我已经使用fyrie测试了这个(除了我不喜欢API之外)它的行为与这个Sedis实现几乎相同.
但这不是我的问题.我只是想了解更多关于playframework/scala的这一部分.
有建议的行为吗?或者有人能指出我更好的方向?我现在开始使用scala,我远非专家,但我可以自己完成代码答案.
谢谢你的帮助.
在篡改了池中的线程数后,我发现:Runtime.getRuntime().availableProcessors()*20
为我的服务提供了大约15%到20%的性能提升(以每秒请求数和平均响应时间来衡量),这实际上使它比node.js稍微好一些(但几乎没有).所以我现在有更多的问题: - 我测试了15x和25x,20似乎是一个甜蜜点.为什么?有任何想法吗? - 是否会有更好的其他设置?其他"甜蜜点"? - 20倍的最佳位置还是依赖于我正在运行的机器/ jvm的其他参数?
找到有关play框架文档的更多信息. http://www.playframework.com/documentation/2.1.0/ThreadPools
对于IO,他们会为我所做的事情提供建议但是通过可通过*.conf文件配置的Akka.dispatchers提供了一种方法(这应该让我的操作开心).
所以现在我正在使用
implicit val redis_lookup_context: ExecutionContext = Akka.system.dispatchers.lookup("simple-redis-lookup")
Run Code Online (Sandbox Code Playgroud)
配置调度程序
akka{
event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
loglevel = WARNING
actor {
simple-redis-lookup = {
fork-join-executor {
parallelism-factor = 20.0
#parallelism-min = 40
#parallelism-max = 400
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
它给了我大约5%的提升(现在眼睛看它),并且一旦JVM"热",性能就会更稳定.我的系统管理员很乐意在不重建服务的情况下使用这些设置.
我的问题仍在那里.为什么这个数字?
And*_*ock 11
我对优化的看法是:
单线程优化
单个线程的性能通常会在代码的单个组件或部分上进行门控,它可能是:
但是,如果可以运行多个线程,单线程中的延迟并不那么令人担忧.当一个线程被阻塞时,另一个线程可以使用CPU(用于交换上下文并替换CPU缓存中的大多数项目的开销).那么你应该运行多少个线程?
多线程
让我们假设线程在CPU上花费大约50%的时间,在50%时等待IO.在这种情况下,每个CPU可以被2个线程充分利用,并且您可以看到吞吐量提高2倍.如果线程花费大约1%的时间使用CPU,那么你应该(所有条件相同)能够同时运行100个线程.
然而,这是可能发生许多奇怪效果的地方:
nx 增加线程,你将永远无法完全n提高x吞吐量.在关键点之后,当你增加时n,你的表现会降低.如果发生这种情况,那么您需要重新考虑算法,更改服务器,网络或网络服务或降低并行度.
影响您可以运行多少个线程的因素
从上面可以看出,涉及到一定数量的因素.因此,线程/核心的最佳位置是多种原因的事故,包括:
根据经验,没有神奇的公式来计算先验最佳线程数.正如你所做的那样,这个问题最好通过经验解决(如上所示).如果需要进行概括,则需要在您选择的操作系统上对不同CPU架构,内存和网络的性能进行抽样.
几个容易观察的指标在这里很有用:
如果您需要优化,请获得最佳的分析工具.您需要一个特定的工具来监控操作系统(例如DTrace for Solaris),一个用于JVM(我个人喜欢JProfiler).这些工具可让您精确放大我上面描述的区域.
结论
碰巧您的特定代码,在特定的Scala库版本,JVM版本,操作系统,服务器和Redis服务器上运行,以便每个线程在95%的时间内等待I/O. (如果运行单线程,则会发现CPU负载约为5%).
这允许大约20个线程在此配置中以最佳方式共享每个CPU.
这是最佳点,因为:
| 归档时间: |
|
| 查看次数: |
903 次 |
| 最近记录: |