Javaでフォーク/ジョインやったらReal時間 < CPU時間になった
現場でマルチスレッド処理を手がけており、それ関係のFWを触っていたら面白いことを知ったのでメモ。
Javaのマルチスレッド FWとは
Javaでは昔からマルチスレッドでプログラミングするためのクラスが用意されていたが、Java5とJava7から新しいFWが出てきた。
整理すると...
Java5で実装
- タスクの非同期処理周りを隠蔽するExecutorService
- ↑のインターフェースの実装クラスを生成するExecutorsクラスとnew***(); メソッド
Java7で実装
- ExecutorServiceインターフェースを実装したForkJoinPoolなどのクラス。newで生成可能。
トランザクションを非同期で発行するだけならJava5までのやり方のほうが(オーバーヘッドがなくて)よく、 再帰的な(=スレッドを無数に生成する)処理ならフォーク/ジョインを使うのがよいらしい。
参考:
multithreading - Java's Fork/Join vs ExecutorService - when to use which? - Stack Overflow
今回はJava7で追加された前者でいきます。
パフォーマンス測定手法
マルチスレッドのプログラムのCPU時間の測り方を見るのが目的!
フィボナッチ数列をシングルスレッド/マルチスレッドでそれぞれ計算するプログラムを作りました。
これらをターミナルから実行し、timeコマンドで測定します。
シングルスレッドとマルチスレッドの性能比較ではないので悪しからず
作ったプログラム
シングルスレッド版
gist.github.com
マルチスレッド版
gist.github.com
計測結果
$ time java Fib 1134903170(←注:計算結果) real 0m7.859s user 0m7.429s sys 0m0.167s $ time java Fib7 1134903170 real 0m30.679s user 1m40.597s sys 0m0.863s
シングルスレッドではreal ≒ user + sys なのに対し、マルチスレッドでは real > user + sys である。これはどういうことか。
なぜReal時間 < CPU時間なのか
要するに各スレッドで使用したCPU時間の合計が表示されるらしい。
参考にさせていただいた記事。
real time/user CPU time/system CPU timeの違いをメモ | Siguniang's Blog
参考資料
Oracleさんのドキュメント
Executors (Java Platform SE 7)
ExecutorService (Java Platform SE 7)
ForkJoinPool (Java Platform SE 8)
実装の参考にさせていただいたブログ記事
ExecutorServiceを使って、Javaでマルチスレッド処理 - Qiita