のスイッチIは、センサ情報を収集するためにシリアルデバイスとインターフェース2つのアッカScalaのアプリケーションを維持し、開発しています。 2つの主な違いは、1つのCPU(My CO2センサーアプリケーション)が1%のCPUを使用し、もう1つ(マイパワーセンサーアプリケーション)が250%のCPUを使用することです。これはLinuxマシン(Raspberry Pi 3)と私のWindowsデスクトップPCの両方のケースです。コード上、主な相違点は、CO2がシリアルライブラリ(http://fazecast.github.io/jSerialComm/)を直接使用しているのに対し、PowerセンサーアプリケーションはシリアルライブラリのIn/OutputStreamをAkkaソース/シンクに変換するためのミドルウェア層を通過するということです。高いCPU使用率がアッカアプリケーション
- この情報を使用して https://stackoverflow.com/a/29414580/1122834:私は次のように答えを見つけることがUnsafe.parkのためにグーグルで後:私は、私はすぐにそれに反対プロファイラ(VisualVMの)平手打ちこの高いCPU使用率を見たとき
val port = SerialPort.getCommPort(comPort)
port.setBaudRate(baudRate)
port.setFlowControl(flowControl)
port.setComPortParameters(baudRate, dataBits, stopBits, parity)
port.setComPortTimeouts(timeoutMode, timeout, timeout)
val isOpen = port.openPort()
if(!isOpen) {
error(s"Port $comPort could not opened. Use the following documentation for troubleshooting: https://github.com/Fazecast/jSerialComm/wiki/Troubleshooting")
throw new Exception("Port could not be opened")
}
(reactive.streamSource(port.getInputStream), reactive.streamSink(port.getOutputStream))
は、以下の私に言いましたパワーセンサーアプリの有無にかかわらずコンテキスト切り替えの量を確認したところ、結果は非常に明確でした問題の根本的な原因:あなたが見ることができるように
[email protected]:~ $ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
10 0 32692 80144 71228 264356 0 0 0 5 7 8 38 5 55 2 0
1 0 32692 80176 71228 264356 0 0 0 76 12932 18856 59 6 35 0 0
1 0 32692 80208 71228 264356 0 0 0 0 14111 20570 60 8 32 0 0
1 0 32692 80208 71228 264356 0 0 0 0 13186 16095 65 6 29 0 0
1 0 32692 80176 71228 264356 0 0 0 0 14008 23449 56 6 38 0 0
3 0 32692 80208 71228 264356 0 0 0 0 13528 17783 65 6 29 0 0
1 0 32692 80208 71228 264356 0 0 0 28 12960 16588 63 6 31 0 0
[email protected]:~ $ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 32692 147320 71228 264332 0 0 0 5 7 8 38 5 55 2 0
0 0 32692 147296 71228 264332 0 0 0 84 963 1366 0 0 98 2 0
0 0 32692 147296 71228 264332 0 0 0 0 962 1347 1 0 99 0 0
0 0 32692 147296 71228 264332 0 0 0 0 947 1318 1 0 99 0 0
は、コンテキストスイッチの量はちょうど私のアプリケーションを殺すことによって〜12000秒でダウンしました。私は、正確なスレッドがこれをやっていたそのチェックによって続け、そしてアッカがものを行うことは本当に熱望しているようだ:
ここでコメントし、アッカの並列処理の設定を微調整に向けた別のSO質問ポイントの両方。私は次のものを私のapplication.confに追加しました。結果はありません。
akka {
log-config-on-start = "on"
actor{
default-dispatcher {
# Dispatcher is the name of the event-based dispatcher
type = Dispatcher
# What kind of ExecutionService to use
executor = "fork-join-executor"
# Configuration for the fork join pool
default-executor {
fallback = "fork-join-executor"
}
fork-join-executor {
# Min number of threads to cap factor-based parallelism number to
parallelism-min = 1
# Parallelism (threads) ... ceil(available processors * factor)
parallelism-factor = 1.0
# Max number of threads to cap factor-based parallelism number to
parallelism-max = 1
}
# Throughput defines the maximum number of messages to be
# processed per actor before the thread jumps to the next actor.
# Set to 1 for as fair as possible.
throughput = 1
}
}
stream{
default-blocking-io-dispatcher {
type = PinnedDispatcher
executor = "fork-join-executor"
throughput = 1
thread-pool-executor {
core-pool-size-min = 1
core-pool-size-factor = 1.0
core-pool-size-max = 1
}
fork-join-executor {
parallelism-min = 1
parallelism-factor = 1.0
parallelism-max = 1
}
}
}
}
これはCPU使用率(100% - > 65%)を向上させるようですが、CPU使用率が不必要に高くなります。
UPDATE 21-11 -'16 グラフ内に問題があるようです。グラフを実行していないときは、CPU使用率はすぐに通常のレベルに低下します。グラフは次のとおりです。
val streamGraph = RunnableGraph.fromGraph(GraphDSL.create() { implicit builder =>
import GraphDSL.Implicits._
val responsePacketSource = serialSource
.via(Framing.delimiter(ByteString(frameDelimiter), maxFrameLength, allowTruncation = true))
.via(cleanPacket)
.via(printOutput("Received: ",debug(_)))
.via(byteStringToResponse)
val packetSink = pushSource
.via(throttle(throttle))
val zipRequestStickResponse = builder.add(Zip[RequestPacket, ResponsePacket])
val broadcastRequest = builder.add(Broadcast[RequestPacket](2))
val broadcastResponse = builder.add(Broadcast[ResponsePacket](2))
packetSink ~> broadcastRequest.in
broadcastRequest.out(0) ~> makePacket ~> printOutput("Sent: ",debug(_)) ~> serialSink
broadcastRequest.out(1) ~> zipRequestStickResponse.in0
responsePacketSource ~> broadcastResponse.in
broadcastResponse.out(0).filter(isStickAck) ~> zipRequestStickResponse.in1
broadcastResponse.out(1).filter(!isStickAck(_)).map (al => {
val e = completeRequest(al)
debug(s"Sinking: $e")
e
}) ~> Sink.ignore
zipRequestStickResponse.out.map { case(request, stickResponse) =>
debug(s"Mapping: request=$request, stickResponse=$stickResponse")
pendingPackets += stickResponse.sequenceNumber -> request
request.stickResponse trySuccess stickResponse
} ~> Sink.ignore
ClosedShape
})
streamGraph.run()
broadcastResponseからフィルタを削除すると、CPU使用率が通常のレベルに低下します。これは、ジップが起こらないと信じるようになります。したがって、グラフは不正な状態になります。
デフォルトディスパッチャとblocking-ioディスパッチャの並列数を減らしてください。ワークロードが通常CPUにバインドされていない場合は、thread-pool-executorに切り替えることを検討してください。 –
@ViktorKlangディスパッチャを調整する際に私が試みたことを反映するために私の質問を編集しました – Lolmewn
デフォルトのblocking-io-dispatcherを再設定していません –