性能計測ユーティリティ
だいぶ前にScalaで書いた性能計測ユーティリティを発掘しました。ScalaなのでJavaクラスの性能計測で使えます。以下はサンプル。
// 関数を5回実行して、処理時間の平均・最大・最小を出力する。 print( Perf.perf( "test", 5 ) { Thread.sleep(500); }.toString )
実行結果です。「平均,最大,最小 [各処理時間]」です。
---test 500, 501, 500 [ 500 501 500 500 500 ]
ユーティリティの実装は次の通り。
/** * 性能計測ユーティリティ */ object Perf { /** * 指定された回数 proc を実行し、所要時間の平均、最大、最小値を出力する。 */ def printPerf[R]( id:String, count:Int )( proc: =>R ):R = { val result = perf( id, count )( proc ) println( result ) result.result } /** * 指定された回数 proc を実行し、所要時間の平均、最大、最小値を出力する。 */ def printPerfTime( id:String, count:Int )( proc: =>Long ):Unit = { val result = perfTime( id, count )( proc ) println( result ) } /** * 指定された回数 proc を実行し、所要時間の平均、最大、最小値を返す。 */ def perf[R]( id:String, count:Int )( proc: =>R ):PrefResult[R] = { // 初回のクラスロード時間を抑制するため // 1度実行する var result = proc var datas:List[Long] = Nil for ( i <- 1 to count ) { val start:Long = System.currentTimeMillis proc datas = (System.currentTimeMillis - start) :: datas } PrefResult[R]( id, datas, result ) } /** * 指定された回数 proc を実行し、所要時間の平均、最大、最小値を返す。 */ def perfTime( id:String, count:Int )( proc: =>Long ):PrefResult[Unit] = { // 初回のクラスロード時間を抑制するため // 1度実行する var result = proc var datas:List[Long] = Nil for ( i <- 1 to count ) { val start:Long = System.currentTimeMillis datas = (proc - start) :: datas } PrefResult[Unit]( id, datas, () ) } } /** * 計測結果 * @param id 計測の識別子 * @param datas 計測結果の配列 */ case class PrefResult[R]( id:String, datas:List[Long], result:R ) { /** 最大値 */ def max = datas.reduceLeft( (max,i) => i max max ) /** 最小値 */ def min = datas.reduceLeft( (min,i) => i min min ) /** 平均 */ def avg = datas.reduceLeft( (sum,i) => sum+i ) / datas.size override def toString:String = { var str = new StringBuilder str.append( "\n---" ).append(id).append("\n") str.append( avg ).append(", ").append( max ).append(", ").append( min ).append(" [ ") datas.foreach( i=> str.append( i ).append(" ") ) str.append("]\n") str.toString } }
ビルドにMavenを使っているJavaプロジェクトであれば、Scalaもさくっと使えるので、テストケースとか性能計測で有効活用したいところですな。