Diese Präsentation wurde erfolgreich gemeldet.
Die SlideShare-Präsentation wird heruntergeladen. ×

Java EE パフォーマンスTips #glassfish_jp

Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Nächste SlideShare
Java EE8 Report
Java EE8 Report
Wird geladen in …3
×

Hier ansehen

1 von 32 Anzeige

Weitere Verwandte Inhalte

Diashows für Sie (20)

Andere mochten auch (16)

Anzeige

Ähnlich wie Java EE パフォーマンスTips #glassfish_jp (20)

Anzeige

Aktuellste (20)

Java EE パフォーマンスTips #glassfish_jp

  1. 1. Java EE パフォーマンスTips 2015/09/16 帰ってきた GlassFish Users Group Japan 勉強会 上妻 宜人 (あげつま のりと)
  2. 2. 上妻 宜人 - あげつま のりと • SIer勤務 • 技術サポート部隊に所属 • Java / Java EE トラブルシューティング • はてな 見習いプログラミング日記
  3. 3. 本日のテーマ
  4. 4. Java EEレイヤ毎の性能Tips Presentation Business Logic Repository • JSF • JAX-RS • .... • EJB • CDI • JPA/JDBC • 外部API呼出 • ファイル I/O
  5. 5. Java EEパフォーマンスTips • プレゼンテーション層 (JSF) • #1 古いmojarraを使わない (JAVASERVERFACES-2494対策) • ビジネス層 (EJB/CDI) • #2 DIはEJBではなくCDIを使う • #3 @Asynchronous利用時はスレッドプールに注意 • データアクセス層 (JPA) • #4 JPAのexecuteBatch設定を忘れない
  6. 6. #1 古いmojarraを使わない (JAVASERVERFACES-2494対策)
  7. 7. #1 古いmojarraを使わない • JSF参照実装mojarraには、かつて性能バグがあった • JAVASERVERFACES-2494 (https://java.net/jira/browse/JAVASERVERFACES-2494) • JSFタグ (UIComponent) が増えると遅くなる問題 • 2.1.22, 2.2.1 で修正 • GlassFish4.0 が該当。4.1でFix。
  8. 8. GlassFish4.0 と Payara4.1 で実測 • 大量のJSFタグがポイント • 1000, 3000, 5000 タグで GlassFish4.0 と Payara4.1 比較 <h:body> <h1>JSF Many Component 1000</h1> <h:form> <h:outputText value="#{testBean.name}"/> <h:outputText value="#{testBean.name}"/> <h:outputText value="#{testBean.name}"/> <h:outputText value="#{testBean.name}"/> <h:outputText value="#{testBean.name}"/> ... 以降大量のoutputTextを繰り返す
  9. 9. タグ数が多い場合は注意 • GlassFish4.0: レスポンスタイムが徐々に低下 • Payara4.1.153 : 5000タグで150ミリ秒 0 1000 2000 3000 4000 5000 1000 2000 3000 4000 5000 レスポンスタイム(ミリ秒) JSFタグ数 GlassFish 4.0 (mojarra2.2.0) Payara 4.1.153 (mojarra2.2.11) マシン情報: MacBook Air corei5 1.7GHz JDK1.8.0_60
  10. 10. mojarraは色々な所で使われている • GlassFish • 4.0は影響あり。 4.1以降で修正。 • Payaraは4.1ベースなので影響なし。 • WildFly • 8.0.0と8.1.0は影響あり。 8.2以降で修正。
  11. 11. Java EEパフォーマンスTips • プレゼンテーション層 (JSF) • #1 古いmojarraを使わない (JAVASERVERFACES-2494対策) • ビジネス層 (EJB/CDI) • #2 DIはEJBではなくCDIを使う • #3 @Asynchronous利用時はスレッドプールに注意 • データアクセス層 (JPA) • #4 JPAのexecuteBatch設定を忘れない
  12. 12. #2 DIはEJBではなくCDIを使う
  13. 13. #2 DIはEJBではなくCDIを使う • Java EE6 CDI が導入。 • Java EE7 より beans.xml なしでデフォルト有効化。 • Java EE5 まではEJB間でのみDIが利用可。 @Inject private StockService service; @Dependent public class StockService { // ... }
  14. 14. EJBのループ呼び出しによるオーバヘッド • EJBのループ呼び出しは性能上悩みの種だった • 万単位以上のループのみオーバヘッド顕在化 • 見つかった時には試験期間の後半
  15. 15. 実際に測っている • Payara4.1.152でBeanをループ呼び出し • EJB と CDI Bean を呼び出して比較 // EJB @Stateless public class EJBBean { public String echo(String s) { return s; } } // CDI @ApplicationScoped public class CDIBean {...} // Client @Inject EJBBean ejb; for (int i = 0; i < loop; i++) { ejb.echo(String.valueOf(i)); }
  16. 16. CDIはほとんどオーバヘッドがない 271 907 2953 1 8 15 10000 50000 100000 EJB @Stateless CDI @ApplicationScoped ループ呼び出し回数 単位: ミリ秒 マシン情報: MacBook Air corei5 1.7GHz JDK1.8.0_60, Payara4.1.153
  17. 17. @Transactionalもループで呼び出してみた • @Transactinal 宣言的トランザクション (Java EE7 〜) • ついうっかり、ループで呼び出される状況を想定 @ApplicationScoped @Transactional public class StockService { public void put(Stock s) { // 更新系処理 ... } public void search(Criteria c) { // 参照系処理 ... } }
  18. 18. @Transactionalはループで呼ばないこと • @Transactional の実体はインターセプタ。 • ループ呼出しコストは高い。 271 907 2953 1 8 151909 8822 32761 10000 50000 100000 EJB @Stateless CDI @ApplicationScoped CDI @ApplicationScoped & @Transactional ループ呼び出し回数 マシン情報: MacBook Air corei5 1.7GHz JDK1.8.0_60, Payara4.1.153 単位: ミリ秒
  19. 19. #3 @Asynchronous利用時は EJBスレッドプールに注意
  20. 20. #3 @Asynchronous利用時はEJBスレッドプールに注意 • @Asynchronousの振り返り • EJB3.1 (Java EE6) で導入 • シンプルに非同期タスク処理が実装できる @Stateless public class AsyncBean { @Asynchronous public Future<String> async() { return new AsyncResult<>("done”); } }
  21. 21. GlassFishデフォルトは多重度が増えない • 以下の非同期EJBの呼び出しは、16多重で止まる • GlassFish4 EJBスレッドプールのデフォルト上限が16 • Performance Tuning Guideにも言及がなく、ハマる @Inject private AsyncBean async; public void callAsyncEjb() { IntStream.range(0, 100) .forEach(i -> async.async()); }
  22. 22. “EJB Container” のプロパティを追加 • 固有の入力欄はなく、プロパティとして設定 • thread-core-pool-size : 最小プールサイズ • thread-max-pool-size : 最大プールサイズ
  23. 23. Java EEパフォーマンスTips • プレゼンテーション層 (JSF) • #1 古いmojarraを使わない (JAVASERVERFACES-2494対策) • ビジネス層 (EJB/CDI) • #2 DIはEJBではなくCDIを使う • #3 @Asynchronous利用時はスレッドプールに注意 • データアクセス層 (JPA) • #4 JPAのexecuteBatch設定を忘れない
  24. 24. #4. JPAのexecuteBatch設定を忘れない • JDBC利用時はexecuteBatchを皆意識する • JPAを使い始めると、何故か忘れやすい • JPA内部で自動的に最適化されている淡い期待 • しかし、EclipseLinkもHibernateもバッチ更新デフォルト無効
  25. 25. EclipseLink のバッチ書き込み設定 • persistence.xml に設定 • eclipselink.jdbc.batch-writing = jdbc (default: none) • eclipselink.jdbc.batch-writing.size = ... (default: 100) <persistence-unit name="PostgresPU"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <jta-data-source>jdbc/postgresDS</jta-data-source> <properties> <property name="eclipselink.jdbc.batch-writing" value="jdbc"/> <property name="eclipselink.jdbc.batch-writing.size" value="100"/> ...
  26. 26. Payara4.1で実際に測ってみる • PostgreSQLに100, 1000, 1万レコードのINSERT • JDBCを加えてO/Rマッパー遅い疑惑も検証 • #1. JDBC executeBatch • #2. JPA batch-writing=jdbc (バッチ有効化) • #3. JPA batch-writing=none (バッチ無効化)
  27. 27. 測定結果 • INSERT 100レコード でも十分な効果がある • JDBCと比較して、JPA(EclipseLink) は1〜2割遅い • 1万行であれば、ORMコストはそれほど大きくない 40 128 122375 169 14891243 9023 58247 100レコード 1000レコード 10000レコード JDBC executeBatch EclipseLink (batch-writing=jdbc) EclipseLink (batch-writing=none) 単位: ミリ秒 マシン情報: MacBook Air corei5 1.7GHz JDK1.8.0_60, Payara4.1.153, PostgreSQL9.3
  28. 28. まとめ
  29. 29. #1 古いmojarraを使わない GlassFish4.1以上 or Payaraを使う (mojarra2.1.22, 2.2.1 以上)
  30. 30. #2 DIはEJBではなくCDIを使う 過ループ時のEJBのオーバヘッドは大きい @Transactionalループ呼び出しに注意
  31. 31. #3 @Asynchronous利用時は EJBスレッドプールに注意 EJBコンテナの以下プロパティを忘れずに設定 thread-core-pool-size, thread-max-pool-size
  32. 32. #4 JPAのexecuteBatch設定を忘れない EclipseLink/Hibernateデフォルトはバッチ無効 persistence.xml eclipselink.jdbc.batch-writing=jdbc

×