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

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

Java SE 8で追加された新機能の中でも特に広い範囲に影響するのが「Date and Time API」、「ラムダ式」、「Stream API」だ。これらの機能の実態を、日本オラクルの伊藤智博氏がパフォーマンスの観点から検証した。

Java SE 8の新機能に対して開発者が抱く疑問


日本オラクル コンサルティング統括本部 プリンシパルコンサルタントの伊藤智博氏

 Java SE 8ではさまざまな新機能が追加されたが、それらの中でも特に広い範囲に影響するのは「Date and Time API」、「ラムダ式(Lambda式)」、そして「Stream API」の3つであろう。これらはJavaプログラムの基本的な構造を変えるものであり、使いこなせば強力な武器になる。だが、日本オラクルの伊藤智博氏(コンサルティング統括本部 プリンシパルコンサルタント)によれば、実際の現場では次のような疑問の声を聞くことが少なくないという。

  • Date and Time APIについて──「従来の日付APIで十分だし、新しいのは処理が重たそう…」
  • ラムダ式について──「使い方が複雑そうだし、処理に時間がかかりそう…」
  • Stream APIについて──「従来のAPIと比べて本当に速いのか?」

 そこで伊藤氏は、パフォーマンス分析の観点から、これらの疑問に答えるべく検証を実施した。本記事では、伊藤氏による3つのAPIの使い方の解説を交えながら、その実行性能の測定結果を紹介する。

 なお、パフォーマンス測定には、Oracle JVMの有償ライセンス「Oracle Java SE Advanced」ユーザーに対して提供されるJVMの稼働情報収集ツール「Java Flight Recorder」が使われた。同ツールを使うことにより、アプリケーション側に特別なコードを埋め込むことなく、極めて低い負荷でCPUやメモリの使用状況などを収集/記録することができる。


※クリックすると拡大画像が見られます

※本記事は、日本オラクルが2016年5月に開催した「Java Day Tokyo 2016」における伊藤智博氏のセッション「オラクルコンサルが語るJava SE 8の勘所」の内容を基に構成しています。

Javaにおける日付と時間の取り扱いを刷新するDate and Time API

 Date and Time APIは、JSR 310(https://jcp.org/en/jsr/detail?id=310)として標準化されている日付と時間を取り扱うためのAPIである。Javaプログラム内で日付や時間を扱う場合、「2016/01/01」などの文字列で表された日付をJavaオブジェクトに変換し、それに対して計算などの処理を行うケースが多い。しかし、従来の日付APIにおける実装は、次に挙げるような多くの問題を抱えていた。

  • フォーマッタがスレッドセーフではない
  • パース用のメソッドが重たい
  • Calendarインスタンスがイミュータブルではない
  • Dateインスタンスが、常に日付と時間の両方を保持するため非効率である
従来の方法で日付/時間を扱うコードの例 従来の方法で日付/時間を扱うコードの例
※クリックすると拡大画像が見られます

 新しいDate and Time APIは、これらの問題を解決するために導入されたものであり、次のような特徴を備える。

  • 従来のAPIとの互換性は持たない
  • スレッドセーフである
  • データ形式ごとにクラスが定義されている
  • イミュータブルである

 伊藤氏は、文字列からオブジェクトへの変換処理を従来のAPIと新APIのそれぞれで実装し、次の2つの観点で計測を行った。

  • 形式を指定してフォーマッタを作成
  • フォーマッタと文字列から日付オブジェクトを作成

 以下に示すのが、比較に用いられたそれぞれのコードだ。ここでご注目いただきたいのは、新旧APIで基本的な処理の流れはほぼ同じであるということだ。これは、旧APIから新APIへの移行は比較的、容易であることを意味する。

日付を扱う新旧コードの比較 日付を扱う新旧コードの比較
※クリックすると拡大画像が見られます

 この検証では、CPUリソースの割り当てやガーベジ・コレクション(GC)の実行時間、変換処理の時間といった観点で分析を行っている。以下がその結果である。

リソース使用量 リソース使用量
※クリックすると拡大画像が見られます
GC停止時間 GC停止時間
※クリックすると拡大画像が見られます
処理時間 処理時間
※クリックすると拡大画像が見られます

 また、オブジェクトのサイズに関する分析も行った。1000万個分の日付オブジェクトを生成/保持したうえでフルGCを実行した後のヒープ使用量を計測した結果が次の図となる。

ヒープ使用量 ヒープ使用量
※クリックすると拡大画像が見られます

 以上の結果から、GCの回数や停止時間は若干増えるものの、変換処理の時間は大幅に短縮されることがわかる。なお、日付オブジェクトのヒープ使用量はほぼ同じだが、データ形式によってはDate and Time APIのほうが増えるケースもあるので注意されたい。