Scala 2.9/Akka 2.0 RC2 코드에서 동시성과 성능을 향상시킬 수있는 기회를 찾고 있습니다. 다음 코드를 감안할 때 : 나는 실행하면다음 Scala + Akka 코드에서 성능/동시성을 향상시킬 수있는 기회는 무엇입니까?
import akka.actor._
case class DataDelivery(data:Double)
class ComputeActor extends Actor {
var buffer = scala.collection.mutable.ArrayBuffer[Double]()
val functionsToCompute = List("f1","f2","f3","f4","f5")
var functionMap = scala.collection.mutable.LinkedHashMap[String,(Map[String,Any]) => Double]()
functionMap += {"f1" -> f1}
functionMap += {"f2" -> f2}
functionMap += {"f3" -> f3}
functionMap += {"f4" -> f4}
functionMap += {"f5" -> f5}
def updateData(data:Double):scala.collection.mutable.ArrayBuffer[Double] = {
buffer += data
buffer
}
def f1(map:Map[String,Any]):Double = {
// println("hello from f1")
0.0
}
def f2(map:Map[String,Any]):Double = {
// println("hello from f2")
0.0
}
def f3(map:Map[String,Any]):Double = {
// println("hello from f3")
0.0
}
def f4(map:Map[String,Any]):Double = {
// println("hello from f4")
0.0
}
def f5(map:Map[String,Any]):Double = {
// println("hello from f5")
0.0
}
def computeValues(immutableBuffer:IndexedSeq[Double]):Map[String,Double] = {
var map = Map[String,Double]()
try {
functionsToCompute.foreach(function => {
val value = functionMap(function)
function match {
case "f1" =>
var v = value(Map("lookback"->10,"buffer"->immutableBuffer,"parm1"->0.0))
map += {function -> v}
case "f2" =>
var v = value(Map("lookback"->20,"buffer"->immutableBuffer))
map += {function -> v}
case "f3" =>
var v = value(Map("lookback"->30,"buffer"->immutableBuffer,"parm1"->1.0,"parm2"->false))
map += {function -> v}
case "f4" =>
var v = value(Map("lookback"->40,"buffer"->immutableBuffer))
map += {function -> v}
case "f5" =>
var v = value(Map("buffer"->immutableBuffer))
map += {function -> v}
case _ =>
println(this.unhandled())
}
})
} catch {
case ex: Exception =>
ex.printStackTrace()
}
map
}
def receive = {
case DataDelivery(data) =>
val startTime = System.nanoTime()/1000
val answers = computeValues(updateData(data))
val endTime = System.nanoTime()/1000
val elapsedTime = endTime - startTime
println("elapsed time is " + elapsedTime)
// reply or forward
case msg =>
println("msg is " + msg)
}
}
object Test {
def main(args:Array[String]) {
val system = ActorSystem("actorSystem")
val computeActor = system.actorOf(Props(new ComputeActor),"computeActor")
var i = 0
while (i < 1000) {
computeActor ! DataDelivery(i.toDouble)
i += 1
}
}
}
를이 (마이크로로 변환) 출력은
elapsed time is 4898
elapsed time is 184
elapsed time is 144
.
.
.
elapsed time is 109
elapsed time is 103
당신은 JVM의 증가 컴파일러에서 발로 볼 수있다 생각
이 빠른 하나. 승리는
에functionsToCompute.foreach(function => {
을 변경할 수 있습니다
functionsToCompute.par.foreach(function => {
는하지만, 이것은 다음과 같은 경과 시간에 결과
elapsed time is 31689
elapsed time is 4874
elapsed time is 622
.
.
.
elapsed time is 698
elapsed time is 2171
일부 정보 :
1) 나는 2 개 코어 맥북 프로에서이 작업을 실행하고 있습니다.
2) 전체 버전에서 함수는 변경 가능한 공유 버퍼의 일부를 루프하는 장기 실행 연산입니다. 액터의 사서함에서 메시지를 가져 오는 것이 흐름을 제어하기 때문에 문제가되지는 않지만 증가 된 동시성으로 인해 문제가 될 수 있습니다. 이것이 내가 IndexedSeq로 변환 한 이유입니다. functionMap에서 모든 항목이 반드시 호출되도록 전체 버전에서
3 은)는 functionsToCompute 목록이 다를 수 있습니다 (예) functionMap.size는 functionsToCompute.size
4) 기능보다 훨씬 클 수 있습니다 병렬로 계산 될 수 있지만, 결과지도
몇 가지 질문을 반환하기 전에 완료해야합니다 :
1) 나는 빠른 병렬 버전 실행을 위해 무엇을 할 수 있는가?
2) 비 차단 및 차단 선물을 추가하는 것이 어디에서 의미가 있습니까?
3) 계산을 다른 배우에게 전달하는 것이 어디에서 의미가 있습니까?
4) 불변성/안전성을 높이기위한 몇 가지 기회가 있습니까?
감사합니다, 요청에 따라 브루스
나는 당신이 당신의 대답으로 무엇을하고 있는지 확신하지 못한다. 그러나 그것은 나에게 흥미로운 점이다. 여기서 akka.dispatch.Future.sequence를 잘 활용할 수있는 것 같습니다. 계산을 수행하고있는 Future의 목록을 만들어 결과 목록에서 Future로 변환합니다. 그 미래가 돌아 오면 필요한 집계표/목록/컨테이너로 결과를 접으십시오. –
@DerekWyatt. 정식 버전에서는 답변이 다른 배우에게 전달됩니다. 귀하의 의견에 감사드립니다. –
왜 각 기능에 대해 하나의 액터가 없습니까? –