オラクルコンサルが語る
Java SE 8 の勘所
日本オラクル株式会社
コンサルティング統括本部
プリンシパルコンサルタント
伊藤 智博
Java Day Tokyo 2016
Safe Harbor Statement
The following is intended to outline our general product direction. It is intended for
information purposes only, and may not be incorporated into any contract. It is not a
commitment to deliver any material, code, or functionality, and should not be relied upon
in making purchasing decisions. The development, release, and timing of any features or
functionality described for Oracle’s products remains at the sole discretion of Oracle.
自己紹介
•
伊藤 智博(いとうちひろ)
•
コンサルティングサービス統括所属
•
インメモリ高速処理基盤の構築を支援
•
Javaに関わるトラブルシューティング
•
国内外問わずJavaのイベントで講演
Java SE 8
について
"旧来の日付APIで十分だし、
"Lambda式?
複雑そうだし、処理に
"Stream API?
こんな疑問を
パフォーマンス分析
の観点で
アジェンダ
1.
Date and Time API
2.
Lambda式
3.
Stream API
Java Flight Recorder
Java Flight Recorderとは
•
アプリケーションとJVMの情報を記録
主な分析観点
•
CPUリソースの割り当て
•
JVMに中断された時間
よく行われる日付の処理
"2016/05/24"
2016/05/24
変換
文字列
日付オブジェクト
2016/05/31
計算
これまでの実装方法
SimpleDateFormat formater =
new
SimpleDateFormat
(
"yyyy/MM/dd"
);
Date date = formater.
parse
(
"2016/05/24"
);
Calendar
cal
= Calendar.getInstance();
cal
.setTime(date);
cal
.set(
DATE
,cal.getActualMaximum(
DATE
));
Date end = cal.getTime();
イミュータブルではない
スレッドセーフではない
重い
Date and Time API とは
•
JSR 310 として標準化された日時API
–
これまでのAPIと互換性は無い
–
スレッドセーフ
–
データ形式ごとにクラスを定義
–
イミュータブル
文字列からオブジェクトへ変換手順
1.
形式を指定してフォーマッタを作成
–
形式の例:yyyy/MM/dd
2.
フォーマッタと文字列からオブジェクトを作成
–
文字列の例:2016/05/24
1
2
"2016/05/24"
変換
2016/05/24
文字列
日付オブジェクト
旧
新
変換コードの比較
SimpleDateFormat formater =
new
SimpleDateFormat(
"yyyy/MM/dd"
);
Date date = formater.parse(
"2016/05/24"
);
DateTimeFormatter
formater =
DateTimeFormatter.ofPattern
(
"yyyy/MM/dd"
);
LocalDate
date =
LocalDate.parse
(
"2016/05/24"
, formater);
1
2
2
1
月末日の取得手順
1.
計算をするための日付オブジェクトの取得
2.
日付オブジェクトに末日を設定
3.
欲しいクラスの日付オブジェクトへ変換
1
2
3
2016/05/24
日付オブジェクト
2016/05/31
計算
旧
新
月末日の取得コードの比較
Calendar cal = Calendar.getInstance();
cal.set(DATE
,cal.getActualMaximum(
DATE
));
Date end = cal.getTime();
LocalDate
end = YearMonth.now().
atEndOfMonth
();
1
2
3
パフォーマンス分析するケース
"2016/05/24"
2016/05/24
変換
文字列
日付オブジェクト
2016/05/31
計算
①
②
ケース1:変換処理
•
処理
–
日付文字列から日付オブジェクトを変換
•
分析観点
–
CPUリソースの割り当て
–
GCの実行時間
–
変換にかかった処理時間
リソースと中断時間を確認
CPUが使えたか
を確認
GCの実行時間を
確認
検証環境
•
ハードウェア
–
CPU 4コア
–
メモリ 16GB
•
Java VM
–
ヒープ 4GB (New 3GB, Eden 2.88GB)
旧
新
ケース1:変換処理のコード比較(再掲
SimpleDateFormat formater =
new
SimpleDateFormat(
"yyyy/MM/dd"
);
Date date = formater.parse(
"2016/05/24"
);
DateTimeFormatter formater =
DateTimeFormatter.ofPattern(
"yyyy/MM/dd"
);
LocalDate date =
リソース使用量
これまでの方法
Date and Time API
1つのコアを使用できている
ケース1:GC停止時間
68.3
71.5
0
20
40
60
80
これまでの方法
Date and Time API
ms
ms
ms
ケース1:処理時間
180
106
0
60
120
180
240
これまでの方法
Date and Time API
秒
秒
秒
ケース2:オブジェクトのサイズ
•
処理
1.
日付オブジェクトを生成・保持
•
1000万オブジェクト
2.
Full GC
•
分析観点
–
FullGCをした後のヒープ使用量
FullGC後のヒープ使用量の確認
GCを選択
FullGC後のヒープ使用量の確認
ケース2: ヒープ使用量
284
284
0
100
200
300
400
java.util.Date
java.time.LocalDate
MB
MB
MB
±
0
%
まとめ
•
処理の流れはほぼ同一に実装可能
•
処理時間は40%以上
短縮
•
日付オブジェクトの
ヒープ使用量は同等
インターフェースについて
インターフェース
本番実装
モック実装
インターフェース
関数型インターフェース
1つのメソッドのみ定義
•
名前付きのクラスによる実装
•
匿名クラスによる実装
インターフェースの実装方法
class
Impl
implements
Iface {
@Override
public void
method1(){
// 処理
}
}
Iface o =
new
Iface() {
@Override
public void
method1(){
// 処理
}
};
これまでの実装方法とその嫌な点
IntPredicate func =
new
Intpredicate(){
public boolean
test(
int
param){
return
param %
2
==
0
;
}
};
開発者は
関心事だけに集中
したい
Lambda式 とは
•
関数型インターフェースを簡単に実装する記法
( 引数 )-> { 本体 }
•
Stream APIとの親和性が高い
•
Java SE 7 以前のインターフェースにも使える
•
実行時に多くのクラスをロード
Lambda式への変換方法
IntPredicate func =
new
Intpredicate(){
public boolean
test(
int
param){
return
param %
2
==
0
;
}
};
IntPredicate func = param
->
param %
2
==
0
;
ケース:実装方法による処理時間
•
処理
–
指定した数が素数かどうかを確認する
–
あえて条件式をLambda式で書いた方法を比較
•
分析観点
–
コンパイル数およびコンパイル時間
–
処理時間
素数とは
•
1とその数自身のみで割りきれる数(2,3,5,7,11,…)
•
素数の候補となる数 n を 2 から n-1 までの数で
割り切れなければ(余り≠0)素数である
コンパイル数の確認方法
コンパイル
された
メソッド数
コンパイル時間の確認方法
コンパイルの
情報から時間を
算出
Copyright © 2016, Oracle and/or its affiliates. All rights reserved. |