Java SE 8のDate and Time API、ラムダ式、Stream APIは本当に使えるか? 従来コードとのパフォーマンス面の違いを検証する

Oracle Java & Developers編集部
2016-08-10 15:00:00
  • このエントリーをはてなブックマークに追加

 伊藤氏は、Stream APIを使った場合のパフォーマンスを、次のようなコードによって検証している。これはfromからtoまでにある素数を数えるプログラムであり、従来のfor文による実装と、クラスStreamを使った実装、そしてパラレル化のためのクラスParalellStreamを使った実装を比較した。

for文で実装したテストコード for文で実装したテストコード
※クリックすると拡大画像が見られます
StreamとParallelStreamで実装したテスト・コード StreamとParallelStreamで実装したテスト・コード
※クリックすると拡大画像が見られます

 なお、この検証はパラレル処理のパフォーマンス測定を含むため、「Oracle Exalogic X5-2」によって最大64並列処理が可能な環境を使用している。

Stream APIのコードの検証環境 Stream APIのコードの検証環境
※クリックすると拡大画像が見られます

 最初に検証したのは、3種類の実装の違いによるリソース使用量と処理時間の違いだ。その結果は次のようになった(この検証ではParalellStreamを使ったコードについても、実行時オプションで最大1スレッドしか使わないよう設定している)。

リソース使用量 リソース使用量
※クリックすると拡大画像が見られます
処理階層の深さ(オーバーヘッド) 処理階層の深さ(オーバーヘッド)
※クリックすると拡大画像が見られます
処理時間 処理時間
※クリックすると拡大画像が見られます

 Stream APIを用いる場合、素数を判断するメソッドにたどり着くまでの処理階層はParalellStreamを使ったコードのほうが深く、オーバーヘッドが大きくなっていることがわかる。ただし、処理時間は若干長くはなるものの、それほど大きな差はないため、影響は軽微と判断してよいだろう。

 続いて、ParalellStreamでパラレル化したコードについて、1から72スレッドまでスレッド数を増やしながらCPU使用率や処理時間の違いを調査した。

 まず、CPU使用率について検証した結果は次のようになる。

1スレッド/3スレッドの場合のリソース使用量 1スレッド/3スレッドの場合のリソース使用量
※クリックすると拡大画像が見られます
18スレッド/36スレッドの場合のリソース使用量 18スレッド/36スレッドの場合のリソース使用量
※クリックすると拡大画像が見られます
36スレッド/72スレッドの場合のリソース使用量 36スレッド/72スレッドの場合のリソース使用量
※クリックすると拡大画像が見られます

 1スレッドに対して1コアが適切に割り当てられている様子がわかる。検証環境は18コア×2CPUで、なおかつHT(Hyper Threading)によって倍のスレッドを同時実行できるため、72スレッドでCPU使用率が100%になっている。

 一方、処理時間についての検証結果は次のようになった。

1~18スレッドの場合の処理時間の推移 1~18スレッドの場合の処理時間の推移
※クリックすると拡大画像が見られます
18スレッド/36スレッドの場合の処理時間の推移 18スレッド/36スレッドの場合の処理時間の推移
※クリックすると拡大画像が見られます
36スレッド/72スレッドの場合の処理時間の推移 36スレッド/72スレッドの場合の処理時間の推移
※クリックすると拡大画像が見られます
スレッド数ごとの処理時間推移のまとめ スレッド数ごとの処理時間推移のまとめ
※クリックすると拡大画像が見られます

 36スレッドまではほぼスレッド数に比例して順調に減少しているが、それ以降はそれほど変動していない。検証環境の実際のコア数は36個であるため、72スレッドを同時に処理しようとするとHTの恩恵が小さくなり、性能が上がりにくいのではないかと伊藤氏は推測する。したがって、HT環境ではCPU使用率に注意する必要があるものの、マルチコア環境でのパラレル化の効果は極めて大きいと言えるだろう。

 これらの結果を踏まえ、伊藤氏はJava SE 8の新機能について、次のように総括している。

 「いずれの機能も、リソース使用量が若干増えるものの、処理時間の短縮効果は決して小さくありません。また、コード量を大幅に削減できることや、関心事に特化したコーディングができるなど、パフォーマンス向上以外の恩恵も受けることができます。アプリケーションの性能や開発効率の向上のためにも、積極的に使うべきだと言えるでしょう」

 以上、本記事ではJava SE 8の新機能であるDate and Time API、ラムダ式、Stream APIについて、パフォーマンスの観点から、その利用効果を紹介した。開発生産性や性能の向上を目的に導入された3つの新機能が、確実な効果をもたらすことがおわかりいただけただろう。記事中に挙げた関連記事も参考にして、ぜひこれらの機能をうまく使いこなしていただきたい。