ページ

2013-01-07

ScalaでBusy Waitした


Scalaでビジーウェイトする関数を作ってみました。

ソースコードと結果は以下になります。


// 再帰でbusy wait.
def busyWait(nanosec: Long): Unit = {
@scala.annotation.tailrec
def wait(target: Long, now: Long): Unit = {
(target < now) match {
case true => // 何もしない.
case false => wait(target, System.nanoTime)
}
}
val now = System.nanoTime
wait(now + nanosec, now)
}
// ベンチマーク用
// num回 nanosecでbusyWaitを呼び出し、処理に掛かった時間を返す.
def run(num: Int, nanosec: Long): Seq[Long] = {
def runWait(nanosec: Long): Long = {
val start = System.nanoTime
busyWait(nanosec)
System.nanoTime - start
}
for(i <- 0 until num) yield {runWait(nanosec)}
}
// runを実行して平均値を表示.
def execBenchmark(num: Int)(nanosec: Long) = {
def printMean(list: Seq[Long]) = {
println("mean => " + list.sum / list.size)
}
println("------ " + nanosec + " [ns] ------")
printMean(run(num, nanosec))
println
}
// 繰り返し回数は固定
val exec10000Times = execBenchmark(10000) _
// 適用に実行.
List[Long](1000,
2000,
3000,
4000,
5000,
6000,
7000,
8000,
9000,
10000,
20000,
30000,
40000,
50000,
100000,
200000,
300000,
1000000,
2000000,
3000000).foreach(exec10000Times)
view raw BusyWait.scala hosted with ❤ by GitHub
------ 1000 [ns] ------
mean => 2093
------ 2000 [ns] ------
mean => 3013
------ 3000 [ns] ------
mean => 4025
------ 4000 [ns] ------
mean => 5025
------ 5000 [ns] ------
mean => 6045
------ 6000 [ns] ------
mean => 7027
------ 7000 [ns] ------
mean => 8054
------ 8000 [ns] ------
mean => 9037
------ 9000 [ns] ------
mean => 10089
------ 10000 [ns] ------
mean => 11043
------ 20000 [ns] ------
mean => 21054
------ 30000 [ns] ------
mean => 31049
------ 40000 [ns] ------
mean => 41066
------ 50000 [ns] ------
mean => 51515
------ 100000 [ns] ------
mean => 101324
------ 200000 [ns] ------
mean => 201272
------ 300000 [ns] ------
mean => 301094
------ 1000000 [ns] ------
mean => 1001368
------ 2000000 [ns] ------
mean => 2001425
------ 3000000 [ns] ------
mean => 3001278
view raw result.txt hosted with ❤ by GitHub

何故こんなことをしたのかというと、Sleepよりもう少し精度が欲しかったから。

実行環境にもよりますが、僕のMBAだと100[usec]位の精度でなら使えると思います。

当然ビジーウェイトなので悲しいほどCPUを消費します。

もっとかっこいい実装方法があったら教えて欲しいです。

後で標準偏差とかも取ってみます。

0 件のコメント:

コメントを投稿