なになれ

IT系のことを記録していきます

Java SE 8のパフォーマンスを簡単に測定してみた

Java SE 8が最近リリースされました。
Java SE 8でJVMに対してパフォーマンスチューニングがされたということを聞き、簡単にパフォーマンスを測定してみました。

・測定方法
100万個のBeanをListに格納する時間を計測

・実行環境
JRE
 Java SE 6U45
 Java SE 7u51
 Java SE 8
IDE
 NetBeans IDE 8.0

・結果
Java SE 6U45 :平均113ms
Java SE 7U51 :平均174ms
Java SE 8 :平均346ms

SE 7から倍くらい遅いという結果になりました。なぜに!?
IDEでやるのがまずいのかと思って、コンソールでも試してみましたが変わらずでした。

測定プログラムは以下のとおり。

package sample;
import java.util.ArrayList;

public class Benchmark1 {

     public static void main(String[] args) {
          for(int j=0;j<10;j++){
              long currentTimeMillis = System.currentTimeMillis();
              ArrayList<User> list = new ArrayList<User>();
              Benchmark1 benchmark1 = new Benchmark1();
              for(int i = 0; i < 1000000; i++){
                  list.add(benchmark1.new User("テスト", "テスト県テスト市", "123456"));
              }
              System.out.println(list.size());
              System.out.println(System.currentTimeMillis() - currentTimeMillis);
          }
     }

     public class User{
          private String name;
          private String address;
          private String id;

          public User(String name, String address, String id) {
               super();
               this.name = name;
               this.address = address;
               this.id = id;
          }
          public String getName() {
               return name;
          }
          public void setName(String name) {
               this.name = name;
          }
          public String getAddress() {
               return address;
          }
          public void setAddress(String address) {
               this.address = address;
          }
          public String getId() {
               return id;
          }
          public void setId(String id) {
               this.id = id;
          }
     }

}


Java SE 8ということで、StreamAPIを使う方法でもやりました。結果は変わりませんでした。
mainメソッドを以下のように書き換え。

for(int j=0;j<10;j++){
      long currentTimeMillis = System.currentTimeMillis();
      Benchmark2 benchmark2 = new Benchmark2();
            Stream<User> generate = Stream.generate(() ->; benchmark2.new User("テスト","テスト県テスト市","123456"));
            List<User> list = generate.limit(1000000).collect(Collectors.toList());
            System.out.println(list.size());
      System.out.println(System.currentTimeMillis() - currentTimeMillis);
}

ただ、一概に今回の結果を捉えてはいけないかなと思います。
Java SE 8からJVMのメモリの利用効率を改善したということで、もっと複雑にJVMが動作するプログラムに対してパフォーマンス計測を行った場合にはどうなるかを計測しないといけないと思います。
例えば、Webアプリケーションとか。

時間があれば、別の形でパフォーマンス計測したいと思います。
Javaのバージョンを上げれば、パフォーマンスが上がりますと言えれば、Java8が業務で使える日も近づくかもしれませんので。

Spring MVC Validationを適用する

Spring MVCでValidationを適用する手順を記します。
 
pom.xml
Hibernate Validatiorを使用するためにライブラリをインポートします。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.3.Final</version>
</dependency>
 
Controllerクラス
画面からの値を受け取るエンティティクラスに@Validアノテーションを適用します。
BindingResultクラスの変数にValidationを行った結果が入ります。
bindingResult.hasErrors()で入力チェックエラーが存在するかを判断しています。エラーが存在する場合、上記メソッドの結果がtrueになります。
@RequestMapping(value="/user/create", method=RequestMethod.POST)
public String create(@Valid @ModelAttribute("userModel") UserModel userModel,BindingResult bindingResult , Model model) {

    if(bindingResult.hasErrors()){

        model.addAttribute("userModel", userModel);
        model.addAttribute("status", NEW);
        return "user";
    }
    userService.createUser(userModel);
    model.addAttribute("userModel",userModel);
    model.addAttribute("status", EDIT);
    return "user";
}

 

画面の入力値を扱うエンティティクラスにValidation用のアノテーションを指定します。
下記では@NotEmpty(必須入力用アノテーション)を使用しています。

public class UserModel {
    @NotEmpty
    private String username;
    private String mailaddress;

    public String getUsername() {
        return username;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public String getMailaddress() {
        return mailaddress;
    }
    public void setMailaddress(String mailaddress) {
        this.mailaddress = mailaddress;
    }
}

 

ValidationMessages.properties
エラーメッセージの内容を日本語にするために編集します。
Hibernate Validatiorのjarファイル内にValidationMessages.propertiesが存在します。
デフォルトではこの内容が表示されます。

@NotEmptyは以下のように定義されています。

org.hibernate.validator.constraints.NotEmpty.message = may not be empty
 
デフォルトを上書きする形で、ValidationMessages.propertiesを新たに定義し、プロジェクトのクラスパス内に配置します。
org.hibernate.validator.constraints.NotEmpty.message = 必須入力です。
 
form:errorsタグでエラーメッセージを表示します。
<form:input path="username"/><form:errors path="username"/>
 

Spring MVC + MirageSQL CRUD画面作成

前回のSpring MVC + MirageSQL環境構築に続き、CRUDを行える画面を作成しました。
 
CRUDとは、「作成(Create)」「読み出し(Read)」「更新(Update)」「削除(Delete)」が行えることです。
 
Serviceクラス
前回までで読み出し(Read)は行えていたので、CUDを追加します。
基本のコードは下記のとおりです。
エンティティクラス(Users)を用意し、画面からの値をエンティティクラスにセットします。
sqlManagerクラスのCUDに対応するメソッドを呼び出します。
読み出しの時のように、SQLファイルを用意する必要はありません。
@Transactional
public void createUser(UserModel userModel){
     Users user = new Users();
     user.username = userModel.getUsername();
     user.mailaddress = userModel.getMailaddress();
     sqlManager.insertEntity(user);
}
 
データベースへの操作 呼び出しメソッド
Create insertEntity
Update updateEntity
delete deleteEntity
 
エンティティクラスは下記のように作成します。
@PrimaryKeyアノテーションで主キーになるプロパティを指定します。
public class Users{

     @PrimaryKey(generationType=GenerationType.APPLICATION)
     public String username;

     public String mailaddress;

}
 
Controllerクラス
更新を行うメソッドを例に説明します。
①モデルクラスの初期化
②のupdateメソッドよりも前にこのメソッドの処理は実行されます。
画面からのリクエストパラメータを扱うにはJavaBeansのようなクラスを定義する方法が簡単です。それがここでいうところのモデルクラスです。
updateメソッドでモデルクラスにあたるUserModelクラスを扱うには@ModelAttributeを指定したメソッドの定義が必要です。①の記述のようにモデルクラスを初期化しています。
 
②サービスクラスの呼び出し
①の実装によって、モデルクラス(UserModelクラス)が扱えるようになっています。userModelの値をそのままサービスクラスに渡すだけです。
 
③モデルクラス定義
画面の値に対応したクラスです。
@NotEmptyはバリデーションを行うための記述です。詳しい内容については別の機会に記したいと思います。
 

// ①モデルクラスの初期化
@ModelAttribute("userModel")
public UserModel initUserModel() {
     return new UserModel();
}

// ②サービスクラスの呼び出し
@RequestMapping(value="/user/update", method=RequestMethod.POST)
public String update(@ModelAttribute("userModel") UserModel userModel, Model model) {
     userService.updateUser(userModel);
     model.addAttribute("userModel",userModel);
     model.addAttribute("status", EDIT);
     return "user";
}

// ③モデルクラス定義
public class UserModel {
     @NotEmpty
     private String username;
     private String mailaddress;

     public String getUsername() {
          return username;
     }
     public void setUsername(String username) {
          this.username = username;
     }
     public String getMailaddress() {
          return mailaddress;
     }
     public void setMailaddress(String mailaddress) {
          this.mailaddress = mailaddress;
     }
}
 
 
View(JSP)
View側でもモデルクラスを使用する指定を行う必要があります。
Spring MVCで用意されているformタグを使用します。modelAttribute属性に使用するモデルのキーを指定します。
<form:form modelAttribute="userModel" action="update" method="POST">
・・・入力項目の記述・・・
</form:form>
 
入力項目を表示するために、formタグ内で使用するタグはSpring MVCで用意されているタグを使用する必要があります。
詳細は以下の記事が参考になります。
 
次回は入力チェック(Validator)についての記事を書きたいと思います。
ここまでのサンプルソースを下記に挙げています。
 
参考