アドテク×scala×パフォーマンスチューニング
Post on 07-Jul-2015
6.647 Views
Preview:
DESCRIPTION
TRANSCRIPT
×
~ パフォーマンス改善の心構えと勘ドコロ ~
アドテク × Scala meetup 2014-11-20 @mogproject
アドテク パフォーマンス チューニング
Scala×
Agenda
Demand Side Science の紹介
パフォーマンスチューニング概論
開発フェーズ別のポイント
水谷 陽介 (@mogproject)
Scala Conference in Japan 2013 のスタッフ参加を機に2013年4月 Demand Side Science 入社
フルスタックエンジニア (笑)
前職は SIer のインフラエンジニア (9年)
自己紹介
2012年11月Demand Side Science 株式会社設立
DSS のこれまで
Demand× Side
Science×
2013年
プライベート DSP パッケージ fractale を開発
DSS のこれまで
Demand× Side
Platform×
リアルタイム広告取引 (RTB) における、広告主側のシステム
DSP とは
Supply Side Platform
2013年12月 インターネット広告代理店 オプト グループに参入
2014年10月 ダイナミック・クリエイティブツール unis 提供開始
DSS のこれまで
× ×
ロジックに従って、動的に広告を生成 http://www.opt.ne.jp/news/pr/detail/id=2492
unis
ベンチャーマインドとオプトグループの 強みを活かしつつ
DSS のこれから
Demand× Side
Science×
サイエンスを軸に 様々なプロダクトを生み出していきたい
DSS のこれから
???× ???
Science×
みんなが
DSS のこれから
広告主 ×メディア 利用者×Marketer Publishers Consumer
ハッピーになれる世界を目指して
DSS のこれから
Win × Win Win×
Demand Side Science は
DSS と Scala
創業以来×全てのプロダクトで
Scala を採用しています×
システム構成イメージRDBMS NOSQL
ログストレージ キャッシュ
ログ集計 機械学習
キャッシュ生成 etc.
JavaScript のチューニングについては 今回は触れません
システム構成イメージ
Agenda
Demand Side Science の紹介
パフォーマンスチューニング概論
開発フェーズ別のポイント
システムの課題の解消
インフラコストの削減
パフォーマンスチューニングの目的
高負荷時のアプリケーションの挙動に問題発生
ある条件下でレイテンシー(応答時間) が悪化
バッチ処理の所要時間が目標を超過
開発ツールの動作が遅い
システムの課題の解消
アドテク分野では特に重要
コストが肥大化しがち 大量トラフィック 厳しい応答性能 大規模データベース・ログデータ
配信量増による利益 > インフラ投資額でなければ、そもそもビジネスが成り立たない
インフラコストの削減
パフォーマンスチューニング自体の コスト (≒ エンジニアの労働時間) と
リスク (未知のトラブルを引き起こす可能性) を意識
目的を見失ってはいけない
単純なインフラ増強が最適解の場合も多い
目標を達成できたら、適当な所で手を引く
を繰り返す (場当たり的な対応はNG)
パフォーマンスチューニングの基本
メトリクスの測定
× ボトルネックの特定
仮説を立てて調整×
参考: http://www.atmarkit.co.jp/ait/articles/0501/29/news011.html
http://ja.wikipedia.org/wiki/パレートの法則
“プログラムの処理にかかる時間の 80%
はコード全体の 20% の部分が占める”
— パレートの法則
※個人の感想です。何の根拠もありません。
ボトルネックの傾向
その他 1%
ネットワーク 4%
JVMパラメータ 5%
ライブラリ 5%
OS 10%
Scala 10%
非同期処理・スレッド 15%
データベース (RDBMS/NOSQL)
50%
“正しい実装さえしていれば これまで経験してきたシステムの大半は
I/O バウンド だった”
— 弊社フルスタックエンジニア
※個人的な感想です ※機械学習アルゴリズムは除く
I/O の 3大要素
メモリ × ディスク
ネットワーク×
一般的なPCのオペレーション処理時間
http://norvig.com/21-days.html#answers
CPU命令 1 ナノ秒 = 1/1,000,000,000 秒
CPU L1キャッシュから読み込み 0.5 ナノ秒
CPU 分岐予測の失敗 5 ナノ秒
CPU L2キャッシュから読み込み 7 ナノ秒
mutex のロック/アンロック 25 ナノ秒
メインメモリにアクセス 100 ナノ秒
1Gbps ネットワークで 2KB 送信 20,000 ナノ秒
メインメモリから 1MB 順次読み込み 250,000 ナノ秒
ディスクのシーク 8,000,000 ナノ秒
ディスクから 1MB 順次読み込み 20,000,000 ナノ秒
日本~アメリカ西海岸間のパケット転送往復 150,000,000 ナノ秒=150ミリ秒
http://itpro.nikkeibp.co.jp/article/COLUMN/20100119/343461/
もしもCPU命令1回に1秒かかるならCPU命令 1秒
CPU L1キャッシュから読み込み 0.5秒
CPU 分岐予測の失敗 5秒
CPU L2キャッシュから読み込み 7秒
mutex のロック/アンロック 0.5分
メインメモリにアクセス 1.5分
1Gbps ネットワークで 2KB 送信 5.5分
メインメモリから 1MB 順次読み込み 3日
ディスクのシーク 3ヶ月
ディスクから 1MB 順次読み込み 6.5ヶ月
日本~アメリカ西海岸間のパケット転送往復 5年
https://www.coursera.org/course/reactive week3-2
間寛平 アースマラソン ヨットで太平洋横断
千葉 ~ ロサンゼルス (片道)
2009-01-03 -> 2009-03-11
70日で達成
ちなみに
http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%BC%E3%82%B9%E3%83%9E%E3%83%A9%E3%82%BD%E3%83%B3#.E3.83.A8.E3.83.83.E3.83.88.EF.BC.9A.E5.8D.83.E8.91.89_-
_.E3.83.AD.E3.82.B5.E3.83.B3.E3.82.BC.E3.83.AB.E3.82.B9
バッチ処理で 10KB 程度の小さなファイルを
ディスクから 100万個 読み込んでいた
合計サイズ:
10KB × 1,000,000 ≒ 10GB
本当にあった怖い話
100万回のシークが発生すると8ms × 106 + 20ms × 10,000 ≒ 8,200 sec ≒ 2.5 h
もし10GBのファイル1個で1回のシークで済むと
8ms × 1 + 20ms × 10,000 ≒ 200 sec ≒ 3.5 min
本当にあった怖い話
√
ディスクヘッドの気持ちを考えよう
http://en.wikipedia.org/wiki/Hard_disk_drive
JVM におけるトレードオフの関係
JVM パフォーマンス・トライアングル
メモリ占有空間 ↓
情報処理量 ↑ 応答時間 ↓
Memory Footprint
Throughput Latency
アプリケーションの 最長停止時間 ≒ Full GC の時間
言い換えると
JVM パフォーマンス・トライアングル
省メモリ
情報処理量 応答速度
Compactness
Throughput Responsiveness
C × T × R = k (定数)
JVM パフォーマンス・トライアングル
k に対して C, T, R のどこに比重を置くか変えるのがチューニング
k を増加させるのが最適化 (Optimization)
(Twitter社ソフトウェアエンジニアの発表)
http://www.beyondlinux.com/files/pub/qconhangzhou2011/Everything%20I%20ever%20learned%20about%20JVM%20performance%20tuning%20@twitter%28Attila%20Szegedi%29.pdf
Agenda
Demand Side Science の紹介
パフォーマンスチューニング概論
開発フェーズ別のポイント
1. 要件定義/フィージビリティ 2. 方式設計 3. 環境設計 4. 環境構築/プログラミング 5. システムテスト 6. 運用/保守
開発フェーズ
パフォーマンスに影響がありそうな ポイントを中心に取り上げます
性能要件について関係者の合意を得る
要件定義/フィージビリティ
想定ユーザーID数
日本のインターネット人口: 約1億人
日本のユニークブラウザ数: 2億~数億 増加率は? 情報を保持する期間は? デバイス/ブラウザの種別は? オプトアウトしているユーザの割合は?
要件定義/フィージビリティ
広告配信要求数 月間 impression 数
月間10億件の場合=> 平均すると 400 QPS (Query Per Second)
=> ピーク率 250% とすると 1,000 QPS
RTBの場合、入札率は? 勝率は?
目標応答時間は? コンテンツの容量は?
増加計画は? Cookie Sync リクエストの量は?
要件定義/フィージビリティ
トラッカー受信量 トラッカー発生のタイミング 広告クリックの確率は? コンバージョン(商品購入など)の発生確率は?
要件定義/フィージビリティ
集計に関する要件 集計すべき指標 ユニーク数の集計は必要か? 集計から除外すべき条件はあるか? 誰が、いつ見るのか 広告代理店が二次加工をして広告主にレポートしている? 更新頻度 集計データの保持期間
要件定義/フィージビリティ
ビジネスサイドの制約 売上計画 年末商戦に合わせたい、年度内に売上目標を達成したい、など インフラ予算
市場の変化が激しいアドテクの世界で 正確な見積りを行うのは至難の業であるが、 仮置きでもよいので数字を出すことが大事
要件定義/フィージビリティ
アーキテクチャ設計には前提が必要 性能テストには目標が必要
アーキテクチャ設計 フレームワーク選択
Webフレームワーク データベース選択
RDBMS NOSQL
方式設計
並行プログラミングモデルの設計 ブロッキングをいかに減らすか Future ベース コールバックを利用した関数合成が基本
Actor ベース メッセージパッシング
スレッドプールの設計 スレッドプールのサイズの適正値は本番環境で性能テストを行うまでわからない
方式設計
データベース設計 アクセスパターン/ルックアップ回数
1レコードあたりのサイズ サイズが一定でない場合は分布をモデル化 レコード数 増加率/保持期間 メモリ使用量 DB単体の性能をまず実測する
環境設計
ログ設計 ディスク容量の見積りでは圧縮率を考慮
キャッシュ設計 Redis など、バックアップのために 2倍のキャパシティが必要な場合もあるので注意
環境設計
この段階では、最適化よりも簡潔さ・明快さを優先したほうがよい
“正しいプログラムを速くすることは、
速いプログラムを正しくするより
はるかに、はるかに簡単だ。”
— C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in-depth series)
環境構築/プログラミング
— Donald Knuth
“時期尚早な最適化は諸悪の根源だ。”
— Jon Bentley
“一方で、効率性は無視できない。”
線形より悪いアルゴリズムはできるだけ避ける
推測するな、計測すべしhttp://ja.wikipedia.org/wiki/UNIX哲学
環境構築/プログラミング
sbt コンソールの中で OpenJDK jmh
(Java のベンチマークツール Java Microbenchmark Harness) を使うためのプラグインhttps://github.com/ktoso/sbt-jmh
マイクロベンチマーク: sbt-jmh
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.1.6")
マイクロベンチマーク: sbt-jmh
plugins.sbt
jmhSettingsbuild.sbt
import org.openjdk.jmh.annotations.Benchmark class YourBench { @Benchmark def yourFunc(): Unit = ??? // 計測したい処理を書く}
YourBench.scala
アノテーションを付けるだけ
> run -i 3 -wi 3 -f 1 -t 1
マイクロベンチマーク: sbt-jmh
sbt コンソールを起動し、ベンチマーク実行
計測回数
ウォーミング アップ回数
全体の試行回数スレッド数
[info] Benchmark Mode Samples Score Score error Units[info] c.g.m.u.ContainsBench.listContains thrpt 3 41.033 25.573 ops/s[info] c.g.m.u.ContainsBench.setContains thrpt 3 6.810 1.569 ops/s
マイクロベンチマーク: sbt-jmh
実行結果 (抜粋)
デフォルトではスループット (単位時間あたりの処理回数) が表示される。 (大きほど良い)
http://mogproject.blogspot.jp/2014/10/micro-benchmark-in-scala-using-sbt-jmh.html
Scala 最適化の例
Scala コレクションを正しく使う
関数呼び出しよりも再帰を使う今年の Scala Matsuri で Martin Odersky 先生が発言
高速化ライブラリを試してみる
def f(xs: List[Int], acc: List[Int] = Nil): List[Int] = { if (xs.length < 4) { (xs.sum :: acc).reverse } else { val (y, ys) = xs.splitAt(4) f(ys, y.sum :: acc) }}
本当にあった怖い話 その2
List[Int] の要素を 4つずつグループにして それぞれの和を求める処理を再帰で
scala> f((1 to 10).toList)res1: List[Int] = List(10, 26, 19)
実行例
本当にあった怖い話 その2
List#length の計算量はリストの長さに比例
パラメータ xs の長さを n とすると O(n)
実装は LinearSeqOptimized#lengthhttps://github.com/scala/scala/blob/v2.11.4/src/library/scala/collection/LinearSeqOptimized.scala#L35-43
本当にあった怖い話 その2
関数 f を実行すると、xs.length はn / 4 + 1 回評価される。
つまり f の実行回数も n に比例する
従って、関数 f の計算量は O(n2)
n が大きくなると急速に性能が劣化する
本当にあった怖い話 その2
ちなみに、組み込みメソッドを使えば 1行で書ける
scala> (1 to 10).grouped(4).map(_.sum).toListres2: List[Int] = List(10, 26, 19)
ScalaBlitz
マクロ機能を利用して Scala コレクションの利用を最適化するライブラリ
http://scala-blitz.github.io/
Scala Days 2014 での発表https://parleys.com/play/53a7d2c6e4b0543940d9e549/chapter0/about
ScalaBlitz
システム機能テスト システム間インターフェーステスト 性能テスト 信頼性テスト セキュリティテスト 運用性テスト
システムテスト
単体負荷テスト
シナリオ負荷テスト 現実のユーザ操作を模した負荷
エージング(連続稼働)テスト
性能テスト
Apache 付属
シンプルなベンチマークツールhttp://httpd.apache.org/docs/2.2/programs/ab.html
単純な要件であればこれで十分 最新バージョンの利用を推奨(Amazon Linux プリインストールのバージョンでバグに苦しめられた) コマンド実行例
ab - Apache Bench
ab -C <Cookie名=値> -n <リクエスト件数> -c <同時実行数> “<URL>“
実行結果の例 (一部)
ab - Apache Bench
Benchmarking example.com (be patient)Completed 1200 requestsCompleted 2400 requests(略)Completed 10800 requestsCompleted 12000 requestsFinished 12000 requests(略)Concurrency Level: 200Time taken for tests: 7.365 secondsComplete requests: 12000Failed requests: 0Write errors: 0Total transferred: 166583579 bytesHTML transferred: 160331058 bytesRequests per second: 1629.31 [#/sec] (mean)Time per request: 122.751 [ms] (mean)Time per request: 0.614 [ms] (mean, across all concurrent requests)Transfer rate: 22087.90 [Kbytes/sec] received(略)Percentage of the requests served within a certain time (ms) 50% 116 66% 138 75% 146 80% 150 90% 161 95% 170 98% 185 99% 208 100% 308 (longest request)
Requests per second = QPS
Apache JMeter の時代は終わった
GUI でシナリオを作るのはつらい
Gatling なら
負荷シナリオを Scala DSL で書ける 必読記事
WEB+DB PRESS Vol.83 (2014/10月) 「Javaの鉱脈」http://gihyo.jp/magazine/wdpress/archive/2014/vol83
筆者 @ryushi さんのブログ http://blog.satotaichi.info/gatling-is-awesome-loadtester
Gatling
負荷をかける側のリソースにも注意 サーバ (PC) のリソース
ネットワークルータの CPU がボトルネックになったことも
一度に 2箇所以上の調整をしない
変更履歴やログファイルをきちんと残す
テスト & チューニングの日々
運用/保守
ログ出力 × 異常検知
トレンド可視化×
日常的にログを記録し、監視する アプリケーションログ GCログ プロファイラー 各種メトリクスによる異常検知 サーバリソース (CPU, メモリ, ディスク等) レスポンスコード異常 レイテンシ 各種メトリクスのトレンド可視化
運用/保守
GCログJVM起動オプションで指定
JVM の運用設定
-verbose:gc-Xloggc:<ログファイルのパス>-XX:+PrintGCDetails-XX:+PrintGCDateStamps-XX:+UseGCLogFileRotation-XX:NumberOfGCLogFiles=10-XX:GCLogFileSize=10M
— Oracle 社の実際の顧客
“本番環境で
GCログを出してない奴は
撃ってやる!”
http://www.oracle.com/technetwork/server-storage/ts-4887-159080.pdf p55
“If someone doesn't enable GC logging in production, I shoot them!”
JMX (Java Management eXtensions)JVM起動オプションに以下を指定
JVM の運用設定
-Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=<ポート番号>-Dcom.sun.management.jmxremote.ssl=false-Dcom.sun.management.jmxremote.authenticate=false
標準出力/標準エラー出力 ファイルにリダイレクトさせる /dev/null に捨てない
スレッドダンプ の結果はここに出る
JVM の運用設定
kill -3 <プロセスID>
SLF4J + Profiler http://www.slf4j.org/extensions.html
コード例
プロファイラー
import org.slf4j.profiler.Profiler
val profiler: Profiler = new Profiler(this.getClass.getSimpleName)
profiler.start(“A”)doA()
profiler.start(“B”)doB()
profiler.stop()logger.warn(profiler.toString)
SLF4J + Profiler 出力例
利用例: タイムアウトが発生時にプロファイラーの結果をログに出力
プロファイラー
+ Profiler [BASIC]|-- elapsed time [A] 220.487 milliseconds. |-- elapsed time [B] 2499.866 milliseconds. |-- elapsed time [OTHER] 3300.745 milliseconds. |-- Total [BASIC] 6022.568 milliseconds.
異常検知ではなく、トレンド把握が目的 変化の兆候を見逃さないような運用も大事 インフラ/アプリだけなく、ビジネス指標も 誰のための画面? システム利用者 システム管理者 アプリ開発者 経営者 (ビジネスの判断を下す人)
メトリクスの可視化
Grafana (+Graphite)
Graphite - http://graphite.readthedocs.org 時系列の数値データを管理/可視化
Grafana - http://grafana.org/ Graphite のデータをカッコよく(Kibana っぽく) 可視化
Graphite にメトリクスを送るScala ライブラリを公開予定
Grafana (+Graphite)
Demand Side Science は
本物の Scala プログラマーを
募集しています。
相談・応募はこちら! ランチご馳走します!
recruit@demand-side-science.jp
DSS 広告
×
~ パフォーマンス改善の心構えと勘ドコロ ~
アドテク × Scala meetup 2014-11-20 @mogproject
ご清聴 ありがとう ございました!
どうも×
"Yosuke Mizutani - Kanagawa, Japan | about.me" - http://about.me/mogproject "mog project" - http://mogproject.blogspot.jp/ "DSS Tech Blog - Demand Side Science ㈱ の技術ブログ" - http://demand-side-
science.jp/blog/ "FunctionalNews - 関数型言語ニュースサイト" - http://functional-news.com/
"『ザ・アドテクノロジー』~データマーケティングの基礎からアトリビューションの概念まで~ / 翔泳社 新刊のご紹介" - http://markezine.jp/book/adtechnology/
"オプト、ダイナミック・クリエイティブツール「unis」の提供開始 ~ パーソナライズ化された広告を自動生成し、広告効果の最大化を目指す ~ | インターネット広告代理店 オプト" - http://www.opt.ne.jp/news/pr/detail/id=2492
"The Scala Programming Language" - http://www.scala-lang.org/ "Finagle" - https://twitter.github.io/finagle/ "Play Framework - Build Modern & Scalable Web Apps with Java and Scala" - https://www.playframework.com/ "nginx" - http://nginx.org/ja/ "Fluentd | Open Source Data Collector" - http://www.fluentd.org/ "Javaパフォーマンスチューニング(1):Javaパフォーマンスチューニングのルール (1/2) - @IT" - http://www.atmarkit.co.jp/ait/articles/0501/29/news011.html
"パレートの法則 - Wikipedia" - http://ja.wikipedia.org/wiki/パレートの法則
"Teach Yourself Programming in Ten Years" - http://norvig.com/21-days.html#answers "企業が作る国際ネットワーク最前線 - [4]いまさら聞けない国際ネットワークの基礎知識:ITpro" - http://itpro.nikkeibp.co.jp/article/COLUMN/20100119/
343461/ "Coursera" - https://www.coursera.org/course/reactive "アースマラソン - Wikipedia" - http://ja.wikipedia.org/wiki/アースマラソン
"Hard disk drive - Wikipedia, the free encyclopedia" - http://en.wikipedia.org/wiki/Hard_disk_drive "Everything I ever learned about JVM performance tuning @twitter(Attila Szegedi).pdf" - http://www.beyondlinux.com/files/pub/qconhangzhou2011/Everything%20I%20ever%20learned%20about%20JVM%20performance%20tuning%20@twitter%28Attila%20Szegedi%29.pdf
"Amazon.co.jp: C++ Coding Standards―101のルール、ガイドライン、ベストプラクティス (C++ in-depth series): ハーブ サッター, アンドレイ アレキサンドレスク, 浜田 光之, Herb Sutter, Andrei Alexandrescu, 浜田 真理: 本" - http://
www.amazon.co.jp/gp/product/4894716860 "UNIX哲学 - Wikipedia" - http://ja.wikipedia.org/wiki/UNIX哲学
"ktoso/sbt-jmh" - https://github.com/ktoso/sbt-jmh "ScalaBlitz | ScalaBlitz" - http://scala-blitz.github.io/ "Parleys.com - Lightning-Fast Standard Collections With ScalaBlitz by Dmitry Petrashko" - https://parleys.com/play/53a7d2c6e4b0543940d9e549/chapter0/about "mog project: Micro Benchmark in Scala - Using sbt-jmh" - http://mogproject.blogspot.jp/2014/10/micro-benchmark-in-scala-using-sbt-jmh.html "Gatling Project, Stress Tool" - http://gatling.io/ "WEB+DB PRESS Vol.83|技術評論社" - http://gihyo.jp/magazine/wdpress/
archive/2014/vol83 "「Javaの鉱脈」でGatlingの記事を書きました — さにあらず" - http://
blog.satotaichi.info/gatling-is-awesome-loadtester "Garbage Collection Tuning in the Java HotSpot™ Virtual Machine" - http://www.oracle.com/technetwork/server-storage/ts-4887-159080.pdf "SLF4J extensions" - http://www.slf4j.org/extensions.html "Graphite Documentation — Graphite 0.10.0 documentation" - http://graphite.readthedocs.org/en/latest/ "Grafana - Graphite and InfluxDB Dashboard and graph composer" - http://grafana.org/ "Grafana - Grafana Play Home" - http://play.grafana.org/#/dashboard/db/grafana-play-home "不動産関係に使える 無料画像一覧" - http://free-realestate.org/information/
list.html "AI・EPSの無料イラストレーター素材なら無料イラスト素材.com" - http://www.無料イラスト素材.com/
"大体いい感じになるKeynoteテンプレート「Azusa」作った - MEMOGRAPHIX" -
http://memo.sanographix.net/post/82160791768
参考文献
top related