Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

10 performanceimprovements 性能改善10事例

4,593 views

Published on

10個の性能問題とその改善に関する話です。

Published in: Software
  • Be the first to comment

10 performanceimprovements 性能改善10事例

  1. 1. 10 Performance Improvements 性能改善10事例 Feb. 18, 2016 Acroquest Technology Co., Ltd. Satoyuki Tsukano
  2. 2. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 2 この発表は、 私が遭遇した 10個の性能問題と その改善に関する話です。
  3. 3. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 3 実際どんな問題が起きたか、 具体的な事例を セキララに紹介します。
  4. 4. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 4 とても苦労するので、 これを聞いた人は、 二度とこのような問題を 起こさないようお願いします。
  5. 5. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 5 マジで!
  6. 6. 目次 1. 背景 ① どんなシステムなの? ② 性能問題への取り組み方 ③ 使ったツールなど 2. 性能改善10事例 3. 振り返り Copyright © Acroquest Technology Co., Ltd. All rights reserved. 6
  7. 7. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 7 背景
  8. 8. どんなシステムなの? 1. とあるWebシステムのバックエンド →ここの性能問題に取り組んだ 2. 言語はJava 3. XMLをインプットにして、 加工したXMLをアウトプットする処理たち 4. Spring、PostgreSQL(MyBatis)、 Couchbase、Elasticsearch等のミドルウェ アを利用 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 8
  9. 9. 性能問題への取り組み方 「遅いよ~」と報告のあった処理に対して、 このステップを繰り返す。(基本パターン) 1. 処理時間を測定 2. 遅い処理に対して、プロファイリングを実施 3. プロファイリング結果を分析し、 遅い箇所を特定 4. 対策を検討 5. 対策を実施 →1に戻って、効果が出たか再測定 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 9
  10. 10. 性能問題への取り組み方 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 10 プロファイリングをベースに、 あくまでも、 科学的に取り組みます。
  11. 11. 性能問題への取り組み方 (真偽はともかく) 「Stringの結合があるから、遅いのでは?」 「正規表現を使った文字列マッチングは、遅い のでは?」 噂や推測だけで、動くのはNG。 実際に測定すると、 ボトルネックは思いもよらぬ所にあったりします。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 11
  12. 12. 使ったツールなど 解析のために使ったもの。 1. ENdoSnipe https://www.endosnipe.com/ https://github.com/endosnipe/ENdoSnipe 2. デバッガ 3. Java付属ツール(jstack、jstat等) 4. ログ ① コンポーネントのin/out ② 他サブシステムとのin/out ③ ミドルウェアとのin/out Copyright © Acroquest Technology Co., Ltd. All rights reserved. 12
  13. 13. 使ったツールなど 5. NetBeans profiler https://profiler.netbeans.org 各メソッドの処理時間をcall treeで見ることができる。 ENdoSnipeと使い分けましょう。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 13
  14. 14. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 14 性能改善10事例
  15. 15. 改善1: Couchbaseアクセスの高速化 1. 状況 ① Couchbaseアクセスが遅い、と報告あり。 ② 1データを取得するのに200ms ③ Couchbaseのjavaクライアントを利用。 com.couchbase.client.java.CouchbaseBucket https://github.com/couchbase/couchbase-java-client Copyright © Acroquest Technology Co., Ltd. All rights reserved. 15
  16. 16. 改善1: Couchbaseアクセスの高速化 2. 分析 ① アプリの処理を確認すると、 Couchbaseアクセス用の共通クラスを作り、 そこで以下の処理を行っていた。 I. Couchbaseに該当のキーが登録されているか確認 (CouchbaseBucket#queryを利用) II. キーの部分一致で検索して、検索結果に対して該当する キーと一致したものがあるか確認 III. キーが存在する場合、CouchbaseBucket#getの結果を 返す。(キーが存在しない場合、nullを返す) ② キーの部分一致で検索したら、 時間かかるのは当たり前。 一方、CouchbaseBucket#getは数ミリ秒で完了し た。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 16
  17. 17. 改善1: Couchbaseアクセスの高速化 3. 対策 ① 存在確認をバッサリ消した。 ② 1アクセス200ms→2msになった。 4. 教訓 API仕様をよく読むこと。 「Couchbaseが遅い」とか言って、ゴメンナサイ。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 17
  18. 18. 改善2: Couchbaseアクセス数の削減 1. 状況 Couchbaseアクセスが遅いのは、解決。 しかし、処理全体はまだ遅かった。 2. 分析 ① Couchbaseに存在するか分からないデータに、 アクセスしている。 ② 「getしてnullが返ってくる」ケースが多く、実際に データが存在するケースは5%程だった。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 18
  19. 19. 改善2: Couchbaseアクセス数の削減 3. 対策 次の処理にする。 ① CouchbaseBucket#queryで存在するキーのリスト を取得。 ② 存在するキーのみCouchbaseBucket#getする。 Couchbase周りの対応により、 処理全体が40秒→5秒に短縮。 4. 教訓 実データの特徴を考慮したアルゴリズムにすること。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 19
  20. 20. 改善3: ディスク経由のコピー処理 1. 状況 多くのシーケンスで、 JAXB#marshal、unmarshalが複数回あり、 2~5秒かかっている。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 20
  21. 21. 改善3: ディスク経由のコピー処理 2. 分析 ① 物理ディスク(XMLファイル)に書き込み→読み込み、 という流れでJAXBオブジェクトをコピーしていた。 ② このプロジェクトでは、通常のJAXBオブジェクトを 加工してあり、親子間で参照を持っていた。 org.apache.commons.beanutils.BeanUtils#copyPropertiesは使 えない。 ③ XMLを経由する処理は尊重する。 ただし、メモリ上でXMLを経由して、コピーする。 OutputStreamからInputStreamに、高速にコピー したい! Copyright © Acroquest Technology Co., Ltd. All rights reserved. 21
  22. 22. 改善3: ディスク経由のコピー処理 3. 対策(java.io.PipedInputStream) ① PipedInputStreamを利用できないか? ② 試しに使ったら、本当にデッドロックしました。 authorはJames Goslingさんでした。 ③ javadocに書いてあった。スレッド間でStreamを やりとりする場合に使うもの。 ⇒別のライブラリを探そう。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 22 単一のスレッドから両方のオブジェクトを使用することは、ス レッドがデッドロックする可能性があるため推奨されていま せん。(javadocより引用)
  23. 23. 改善3: ディスク経由のコピー処理 3. 対策(org.apache.commons.io.IOUtils) ① IOUtilsを利用できないか? ② IOUtils#copyがあるが、 InputStreamをOutputStreamにコピーするもの。 ③ 今回は逆なので、使えない。 ⇒別のライブラリを探そう。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 23
  24. 24. 改善3: ディスク経由のコピー処理 3. 対策(netty-buffer) ① netty-bufferを利用すれば、解決する。 (通信フレームワークNetty内のライブラリ) ② しかも、コピー回数が2回で済む。 単純に考えると、コピー的な処理が3回必要。 OutputStreamとInputStreamが保持するバッファ を共有すれば、コピー的な処理は2回で済む。 リ Copyright © Acroquest Technology Co., Ltd. All rights reserved. 24 アプリ OutputStream InputStream アプリ アプリ OutputStream & InputStream アプリ
  25. 25. 改善3: ディスク経由のコピー処理 4. 教訓 不必要にディスクアクセスしないこと。 (「netty-bufferなんて、知らないよ」との声も) Copyright © Acroquest Technology Co., Ltd. All rights reserved. 25
  26. 26. 改善4: JAXBContextの初期化処理 1. 状況 ディスク経由のコピーで遅いのは、解決。 しかし、処理全体ではまだ遅かった。 2. 分析 ① ときどき、JAXB#marshal、unmarshalそのもの が遅い。1回の呼び出しで数百msかかることが ある。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 26
  27. 27. 改善4: JAXBContextの初期化処理 2. 分析 ② コードを見てみると、 javax.xml.bind.JAXBContext#getContextで static変数にJAXBContextをキャッシュしていた。 1回前の呼び出しと、JAXBオブジェクトのクラス 毎が同じ場合はキャッシュが利用されて高速。 異なるクラスの場合は、JAXBContextの初期化 が走る。 ③ 「これじゃ、まともに使えないよ!」と思いました。 authorはKohsuke Kawaguchiさんでした。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 27
  28. 28. 改善4: JAXBContextの初期化処理 2. 分析 ④ javadocを見てみると、ちゃんと書いてありました。 ⑤ すみません、こちらが悪かったです。 3. 対策 ① JAXBオブジェクトのクラス毎にJAXBContextを 自力でキャッシュするようにした。 ② 1回目は遅いが、2回目以降の処理は高速になった。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 28 一般に、性能は必ずしも最適とは限りません。性能が重視されるコードを記述する必要の あるユーザーは残りの JAXB API を直接使用するものと見られています。(javadocより 引用)
  29. 29. 改善4: JAXBContextの初期化処理 4. 教訓 API仕様をよく読むこと。 「使えない」とか言って、ゴメンナサイ。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 29
  30. 30. 改善5: DBアクセス時のリフレクション処理 1. 状況 DBアクセス時にエンティティクラスのコピー がある。(このシステムでは、この処理は必 要な前提) ここでリフレクションを利用しており、各処理 が1-2秒ずつ遅くなっていた。 2. 分析 状況に書いた通り。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 30
  31. 31. 改善5: DBアクセス時のリフレクション処理 3. 対策 ① リフレクションを利用しないようにする。 getter/setterメソッドでコピーする。 ② 50テーブル(=エンティティ)とか、手じゃ書けない。 ③ Velocity を使い、MyBatisの設定ファイルから、 コピー処理を自動生成した。 4. 教訓 大量に実行する処理では、リフレクションを 使わないこと。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 31
  32. 32. 改善6: DBアクセス時の大量insert処理 1. 状況 ある処理に80秒かかっているが、 機能的には、数秒で完了しても良いくらい。 2. 分析 ① DBに対して大量のinsertが発生しており、それ だけで半分近くの時間を使っている。 ② 特に4テーブルに対するinsertが頻発しており、 各テーブルに対して3~4桁のinsertが発生して いた。 ③ Selectした結果を、そのまま1レコードずつ insertしていた。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 32
  33. 33. 改善6: DBアクセス時の大量insert処理 3. 対策 テーブル毎に、1SQLにまとめて select & insertを行うようにする。 80秒かかった処理が2秒になりました。 4. 教訓 大量のSQL文を発行せず、 まとめて処理すること。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 33
  34. 34. 改善7: ObjectのgetClass処理 1. 状況 巨大なデータを処理したところ、7分かかった。 もっと短くしたい。 2. 分析 Object#getClassが累積2分半程度かかっ ていた。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 34
  35. 35. 改善7: ObjectのgetClass処理 3. 対策 ① クラス名によりcase文を切り替える共通処理が あり、ここでgetClassを呼び出していた。この処 理の呼び出し回数が多いため、処理時間がか かっている。 ② getClassを使わなくて済むように、case文での 処理を各クラスで実行するようにした。(設計的 にも、その方が自然だった) 4. 教訓 大量のgetClassには注意すること。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 35
  36. 36. 改善8: デバッグログ出力処理 1. 状況 巨大なデータを処理は4分半になったが、 もっと短くしたい。 2. 分析 ① デバッグログに出力する文字列の作成に累積 30秒かかっていた。 ② Infoレベルで実行しているにも関わらず! Copyright © Acroquest Technology Co., Ltd. All rights reserved. 36
  37. 37. 改善8: デバッグログ出力処理 3. 対策 ① デバッグ文はisDebugEnabledで囲うようにした。 ② あまりに基本的なケアレスミスなので、 コードを埋め込んだ担当者に食事に奢ってもら う約束をした。 ③ ObjectのgetClass処理改善と合わせて、 巨大なデータ処理が7分→4分になった。 4. 教訓 デバッグ文はisDebugEnabledで囲うこと。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 37
  38. 38. 改善9: 無駄なスレッド生成処理 1. 状況 48時間連続稼働試験を行った際に、 スレッド数がじわじわ増加していくのを ENdoSnipeで検知した。 2. 分析 スレッドダンプを取得し、増加しているスレッ ドを特定した。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 38
  39. 39. 改善9: 無駄なスレッド生成処理 3. 対策 ① 特定シーケンスで生成したスレッドが残り続け ていた。 ② 担当者に確認したところ、以前、不要になったス レッド処理だったことが判明。そのスレッド処理 をバッサリと削除した。 4. 教訓 ① 不要になった処理は削除すること。 ② ENdoSnipeを使ってチェックすること。(今回は チェックしたので検出できた) Copyright © Acroquest Technology Co., Ltd. All rights reserved. 39
  40. 40. 改善10: メモリリークによるOOM-Killer 1. 状況 48時間連続稼働試験を行った際に、 OSのメモリ使用量がじわじわ増加する。 挙句の果てに、OOM-Killerが発動してしまう。 2. 分析 ① OOM-Killerの発生時間とアプリのログから、 引き金になったと思われる処理を特定した。 ② その処理を追っていくと、 RAMディスクにファイル を作成する処理があった。また、そのファイルは削 除されることなく残り続けていた。 ③ 処理の都合上、一時的にファイル出力していたが、 処理完了後は不要なファイルだった。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 40
  41. 41. 改善10: メモリリークによるOOM-Killer 3. 対策 ① 極力、ファイル出力しないよう、処理を変更した。 ② ファイル出力が必要な場合も、最終的にファイ ルを削除する処理に変更した。 ③ ファイルの出力先をRAMディスクでなく、物理 ディスクにした。 4. 教訓 RAMディスクの使い方には注意すること。 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 41
  42. 42. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 42 振り返り
  43. 43. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 43 問題の特徴を理解し、 二度と発生させないよう 手を打ちましょう。
  44. 44. 問題の特徴 Copyright © Acroquest Technology Co., Ltd. All rights reserved. 44 No. 問題 教訓 1 Couchbaseアクセスの高速化 API仕様をよく読む 2 Couchbaseアクセス数の削減 実データの特徴を考慮したアルゴリ ズムにする 3 ディスク経由のコピー処理 不必要にディスクアクセスしない 4 JAXBContextの初期化処理 API仕様をよく読む 5 DBアクセス時の リフレクション処理 大量のリフレクションは使わない 6 DBアクセス時の大量insert処理 大量のSQLはまとめて処理する 7 ObjectのgetClass処理 大量のgetClassは使わない 8 デバッグログ出力処理 デバッグ文はisDebugEnabledで囲う 9 無駄なスレッド生成処理 不要になった処理は削除する ENdoSnipeを使ってチェックする 10 メモリリークによるOOM-Killer RAMディスクの使い方には注意する
  45. 45. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 45 教訓① 1回の処理では問題なくても、 大量処理で問題となる ケースを理解すること。
  46. 46. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 46 教訓② API仕様を良く読み、 理解して実行すること。
  47. 47. Copyright © Acroquest Technology Co., Ltd. All rights reserved. 47 教訓③ 難しい箇所は 検討会・レビューなどを 実施すること。
  48. 48. という訳で Copyright © Acroquest Technology Co., Ltd. All rights reserved. 48 とても苦労するので、 これを読んだ人は、 二度とこのような問題を 起こさないようお願いします。
  49. 49. 49 ご清聴ありがとうございました。 これら事例を他山の石にしてください!

×