Bean Validationの各オープンソースプロジェクトの処理時間を比較

JavaにはBean ValidationというAPIが存在していて、これはアノテーションによってバリデーションの制約を定義できるとても便利なものです。

Bean Validationの使い方

何かしらのクラスのメンバ変数に@NotNullとか、@Max(100)などというアノテーションを指定すると、nullでないことの検証や値の最大値の検証が簡単にできます。

public class Bean {
	@NotNull
	String attribute;
	// ...
}

便利です。

Bean Validationの実装の比較

Bean Validationは、Javaの素晴らしき仕様と実装の分離の恩恵を受けていて、このBean Validationを実装したライブラリはひとつではないので、用途に応じて使い分けることができます。
Bean Validation API 1.0の実装の有名どころは、Hibernate ValidatorやApache BVal、GWT Validationなどです。
最近パフォーマンス検証をしていたら、どうもBean Validationがひどく負荷をかけているように感じたので、ひとつ比較をしてみようと思いました。

3つのライブラリの比較の方法

比較の方法を簡単に書いておきます。
Validatorを生成し、それを用いて1000回とか10,000回とかバリデーションをおこない実行時間を計測します。回数依存性を見るために、これを100回くらい立て続けに繰り返します。

ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
for (int j = 0; j < LOOP; j++) {
	long start = System.nanoTime();
	for (int i = 0; i < UNIT; i++) {
		Bean bean = new Bean("attr");
		validator.validate(bean);
	}
	System.out.println(((double) (System.nanoTime() - start) / 1e6));
}

3つのライブラリのMavenの依存定義は次のようにしました。
1つ目は、Hibernate Validatorです。最新の開発バージョンである、5.1.0.Alpha1です。(あとで別のバージョンも比較します)


	org.hibernate
	hibernate-validator
	5.1.0.Alpha1

2つ目は、Apache BValです。


	org.apache.bval
	bval-jsr303
	0.5

そして3つ目はGoogleのプロジェクト。GWT Validationです。


	com.googlecode.gwt-validation
	gwt-validation
	2.1

比較結果

これは@NotNullをつけたクラスを10,000回ずつバリデーションした結果です。
スクリーンショット 2013-09-30 0.55.36
比較すると、Hibernate Validatorが最も高速で、GWT Validationと比較すると桁が違います。どの実装も初回のバリデーションが一番遅く、何回かバリデーションを繰り返すと、処理時間が短くなるようです。くわしく実装は見ていないですが、バリデーションの定義をキャッシュする機構があるようです。
ところで、もともとこの調査をし始めたのは、Bean Validationのために使っているHibernate Validatorが遅いのではないかということを検証するためでした。しかし、実際に測定してみると、Hibernate Validatorは十分に高速でした。

Hibernate Validatorのバージョン比較

もう少し色々と測定して試してみると、Hibernate Validatorの5.0.0.Alpha1の@NotEmptyのバリデーションが遅いことが分かりました。
@NotNullと@NotEmptyをつけたクラスを、1,000回ずつバリデーションして処理時間を計測しています。
スクリーンショット 2013-09-30 0.57.27
この通り、@NotEmptyのバリデーションは、Hibernate Validator 5.0.0.Alpha1では猛烈に遅くなります。回数を重ねるごとにどんどん遅くなっていくので、いずれハングアップすることになります。
@NotEmptyというのは、Bean Validationの仕様自体には存在しないもので、@NotNullと@Size(min=1)の複合的な定義となっています。Hibernate Validatorの5.0.0.Alpha2までは、このバリデーションがとてもヘビーなようです。
もう5.0.0.Alpha2はもう半年以上経過しているしそもそも安定バージョンじゃないので、そんなに使っている人はいないかもしれませんが、せっかく調べたのでメモ書き程度に。

タイトルとURLをコピーしました