The basic of performance tuning

Post on 29-Jun-2015

1.840 views 5 download

Tags:

description

The basic of performance tuning by Higepon at Esper 2008 in Japan

Transcript of The basic of performance tuning

2008/9/13

パフォーマンスチューニングの基礎の基礎

Cybozu Labs, Inc

ひげぽん

higepon@labs.cybozu.co.jp

自己紹介

ひげぽん(蓑輪太郎)Mosh

R6RS Scheme インタプリタhttp://code.google.com/p/mosh-scheme/

Monaオープンソース OS

http://www.monaos.org

2

Mona

3

Mona

オープンソースOS2002年~FD/CD起動GUIフルカラー音ネットワーク

3

未踏ソフトウェアとの関わり

4

未踏ソフトウェアとの関わり

Mona における次世代Schemeシェルの開発2006年度下期 並木PM

Mona の「標準のシェル」にSchemeを採用Scheme からプロセスを起動ウィンドウを操作

4

近況

5

近況

サイボウズ・ラボ株式会社へ転職ソフトウェアの開発・研究

5

近況

サイボウズ・ラボ株式会社へ転職ソフトウェアの開発・研究

R6RS Scheme インタプリタ Mosh 開発中広範囲で使われる Scheme を目指していずれは Mona に移植したい

5

近況

サイボウズ・ラボ株式会社へ転職ソフトウェアの開発・研究

R6RS Scheme インタプリタ Mosh 開発中広範囲で使われる Scheme を目指していずれは Mona に移植したい

5

あれ?自己紹介・近況だけだと間が持たないぞ

6

パフォーマンスチューニングの基礎の基礎

7

パフォーマンスチューニングの問題

こんな経験はありませんか?

8

こんな経験はありませんか?

いくらチューニングしても速くならない

8

こんな経験はありませんか?

いくらチューニングしても速くならないチューニング中に森に迷い込んでしまった

8

こんな経験はありませんか?

いくらチューニングしても速くならないチューニング中に森に迷い込んでしまった速くするには大幅に変更が必要

しかもそれで速くなるかは分からない

8

こんな経験はありませんか?

いくらチューニングしても速くならないチューニング中に森に迷い込んでしまった速くするには大幅に変更が必要

しかもそれで速くなるかは分からない

勘でチューニングしたら速くなった→ Great

速くならない、遅くなった→ orz...8

問題点

9

問題点

方法論がいまいち浸透していない

9

問題点

方法論がいまいち浸透していないコーディング・設計は良い例がたくさん

9

問題点

方法論がいまいち浸透していないコーディング・設計は良い例がたくさんチューニングは?

まだまだ少ない

9

問題点

方法論がいまいち浸透していないコーディング・設計は良い例がたくさんチューニングは?

まだまだ少ない

経験の豊富なプログラマでもチューニング方法は自己流が多い

9

今日の発表

10

今日の発表

パフォーマンスチューニングの基礎の基礎

10

今日の発表

パフォーマンスチューニングの基礎の基礎Mosh の開発での苦労した経験を元に

速いソフトウェアを作りたい人を対象に言語にできるだけ依存しないテクニックを紹介

一部 Mosh 固有のトピック

10

11

パフォーマンスチューニングでやってはいけないこと

その1

12

その1

パフォーマンスは後回しリリース直前にパフォーマンスチューニングすればOK?

12

その1

パフォーマンスは後回しリリース直前にパフォーマンスチューニングすればOK?

最悪の場合どうにもならなくなる

12

その1

パフォーマンスは後回しリリース直前にパフォーマンスチューニングすればOK?

最悪の場合どうにもならなくなる

最初に作った Scheme は遅かった 12

その2

13

その2

自戒の念も込めて

13

その2

自戒の念も込めてここがいかにも遅そうだから

memcached にキャッシュしようインライン展開しようインラインアセンブラにしよう

13

その2

自戒の念も込めてここがいかにも遅そうだから

memcached にキャッシュしようインライン展開しようインラインアセンブラにしよう

誰でも経験があるはず

13

その2

自戒の念も込めてここがいかにも遅そうだから

memcached にキャッシュしようインライン展開しようインラインアセンブラにしよう

誰でも経験があるはずこれはなぜだめか?

13

その2

自戒の念も込めて

ここがいかにも遅そうだからmemcached にキャッシュしようインライン展開しようインラインアセンブラにしよう

14

その2

自戒の念も込めて

ここがいかにも遅そうだからmemcached にキャッシュしようインライン展開しようインラインアセンブラにしよう

14

計測していない!

その2

15

その2

計測せよ直感はまちがいかもその関数一度も呼ばれないかも遅いがユーザー応答時間への影響は少ないかも

15

その2

計測せよ直感はまちがいかもその関数一度も呼ばれないかも遅いがユーザー応答時間への影響は少ないかも

小さなパフォーマンス事項で壊してはだめ良いデザイン機能性柔軟性 15

16

良いデザイン?機能性?柔軟性?

良いデザイン?機能性?柔軟性?

17

良いデザイン?機能性?柔軟性?

memcached にキャッシュしたとするキャッシュ ON/OFF の2通りでテストキャッシュの Expire の境界チェックmemcached 環境の構築コードが増える

17

良いデザイン?機能性?柔軟性?

memcached にキャッシュしたとするキャッシュ ON/OFF の2通りでテストキャッシュの Expire の境界チェックmemcached 環境の構築コードが増える

コードの本来の目的がぼんやりする

17

良いデザイン?機能性?柔軟性?

memcached にキャッシュしたとするキャッシュ ON/OFF の2通りでテストキャッシュの Expire の境界チェックmemcached 環境の構築コードが増える

コードの本来の目的がぼんやりする開発、テスト、改修時に気にする必要

17

Memcached の使用例

18

use Cache::Memcached;

$memd = new Cache::Memcached { 'servers' => [ "10.0.0.15:11211", "10.0.0.15:11212", "/var/sock/memcached", "10.0.0.17:11211", [ "10.0.0.17:11211", 3 ] ], 'debug' => 0, 'compress_threshold' => 10_000, }; $memd->set_servers($array_ref); $memd->set_compress_threshold(10_000); $memd->enable_compress(0);

$memd->set("my_key", "Some value"); $memd->set("object_key", { 'complex' => [ "object", 2, 4 ]});

$val = $memd->get("my_key");

良いデザイン?機能性?柔軟性?

19

良いデザイン?機能性?柔軟性?

inline にしたとする

19

良いデザイン?機能性?柔軟性?

inline にしたとする実装をヘッダに書くor マクロ

build dependencies平均 build 時間が増えるインターフェースが読みづらくなる

19

良いデザイン?機能性?柔軟性?

inline にしたとする実装をヘッダに書くor マクロ

build dependencies平均 build 時間が増えるインターフェースが読みづらくなる

賛否両論ありそう

19

良いデザイン?機能性?柔軟性?

20

良いデザイン?機能性?柔軟性?

インラインアセンブラ

20

uint32_t l,h; asm volatile("rdtsc \n" "mov %%eax, %0 \n" "mov %%edx, %1 \n" : "=m"(l), "=m"(h) : /* no */ : "eax", "edx"); *timeL = l; *timeH = h;

というわけで

21

というわけで

測定せず直感だけで良いデザインを壊すのは NG

21

というわけで

測定せず直感だけで良いデザインを壊すのは NG

でも誤解しないでほしい挙げられたテクニックは有効な場所もあるトレードオフがあるだけ

21

大事なこと

22

パフォーマンスチューニングにはコスト・リスクがあることを理解しよう

23

これらをふまえてどうすれば良いか?

チューニングを開発プロセス

24

チューニングを開発プロセス

開発の最初からチューニングを開発プロセスに取り込む

24

チューニングを開発プロセス

開発の最初からチューニングを開発プロセスに取り込む

最初にゴール・目標を決める

24

チューニングを開発プロセス

開発の最初からチューニングを開発プロセスに取り込む

最初にゴール・目標を決める短いサイクルをまわそう

開発測定チューニング

24

0. 最初にゴール・目標を決める

25

0. 最初にゴール・目標を決める

例500 msec 以内にレスポンスを返す

25

0. 最初にゴール・目標を決める

例500 msec 以内にレスポンスを返す

ゴール・目標がないと今十分速いのか?が分からない後どれくらい速くなればいいか分からない

25

0. 最初にゴール・目標を決める

例500 msec 以内にレスポンスを返す

ゴール・目標がないと今十分速いのか?が分からない後どれくらい速くなればいいか分からない

作る前から正確な目標は立てられないよ?良い指摘

25

1. 開発

26

1. 開発

パフォーマンスのことは考えない

26

1. 開発

パフォーマンスのことは考えない良いデザイン・良いコードに集中

パフォーマンスを気にする時間はすぐ後にある

26

1. 開発

パフォーマンスのことは考えない良いデザイン・良いコードに集中

パフォーマンスを気にする時間はすぐ後にある

でも「ウズウズするんだ」「良い高速化手法思いついた」「もしかしたら遅いかも」

コメントにメモしておく

26

2. 計測

27

2. 計測

目標に到達しているか?計測する

27

2. 計測

目標に到達しているか?計測する短いサイクルで計測する

27

2. 計測

目標に到達しているか?計測する短いサイクルで計測する遅くなったら一つ前の開発が悪い

一つ前なのでコードを良く覚えているあとからチューニングするよりもやりやすい

27

2. 計測

目標に到達しているか?計測する短いサイクルで計測する遅くなったら一つ前の開発が悪い

一つ前なのでコードを良く覚えているあとからチューニングするよりもやりやすい

簡単に計測できる仕組みづくりが大切

27

3. チューニング

28

3. チューニング

目標を満たしていなければ初めてチューニングに取りかかるメモが役に立つかも?

28

まとめると

29

まとめると

短いサイクルをまわそう開発

良いデザイン・良いコードに集中パフォーマンスのことは考えない

測定ゴール・目標満たしている?

チューニング

29

まとめると

短いサイクルをまわそう開発

良いデザイン・良いコードに集中パフォーマンスのことは考えない

測定ゴール・目標満たしている?

チューニング

速いコードをサイクルごとに維持する29

30

測定・チューニングのテクニック

31

測定

環境構築

32

環境構築

初期の環境構築で効率が変わる

32

環境構築

初期の環境構築で効率が変わる測定するデータの準備

より本番に近い形で

32

環境構築

初期の環境構築で効率が変わる測定するデータの準備

より本番に近い形で

測定は楽をしよう気軽に測定できるように測定が楽しくなるように半自動化

make bench など 32

記録と参照

33

記録と参照

目標 1sec

33

記録と参照

目標 1sec

33

チューニング項目 secA 12.29B 10.05C 9.55D 9.53E 7.57F 5.98G 4.4H 4.3

記録と参照

目標 1sec

33

チューニング項目 secA 12.29B 10.05C 9.55D 9.53E 7.57F 5.98G 4.4H 4.3

過去のデータを保持レポジトリに入れる

グラフで一目瞭然

34

グラフを描く

グラフで一目瞭然

34

0

2.5

5.0

7.5

10.0

12.5

15.0

チューニング

グラフを描く

35

チューニング

遅いところはどこか? の道具

36

遅いところはどこか? の道具

プロファイラgcc なら gprof

36

遅いところはどこか? の道具

プロファイラgcc なら gprof

プロファイラがない場合は?ストップウォッチログ方式プロファイラ実装

36

遅いところはどこか? の道具

プロファイラgcc なら gprof

プロファイラがない場合は?ストップウォッチログ方式プロファイラ実装

道具の選定・準備に時間をかけるべし36

37

VM(Mosh)開発固有の話

VM 固有の話

38

VM 固有の話

VM では普通のプロファイラが使えない関数単位のプロファイラ gprof

実行時間の大半が run ループrunループのどこが遅いか分からない

38

VM 固有の話

VM では普通のプロファイラが使えない関数単位のプロファイラ gprof

実行時間の大半が run ループrunループのどこが遅いか分からない

38

Each sample counts as 0.01 seconds. % cumulative self self total time seconds seconds calls ms/call ms/call name 58.33 0.98 0.98 86 11.40 14.55 scheme::VM::run

runループ

39

void run(){ for (;;) { switch(instruction) { case CALL: /* 何か */ case XXX: /* 何か */ case YYY: /* 何か */ } ... たくさん続く }}

どの命令が遅いか分からない

qprof

40

qprof

qprof はどのアドレスが遅いかが分かる命令(ラベル)のアドレスとマッチング可能

40

qprof

qprof はどのアドレスが遅いかが分かる命令(ラベル)のアドレスとマッチング可能

40

qprof -ginstruction -i 1 -o qprof.log ./mosh

scheme::VM::run(scheme::Object) [0x8051c8b] 12 ( 4%)scheme::VM::run(scheme::Object) [0x8051c92] 2 ( 1%)scheme::VM::run(scheme::Object) [0x8051d84] 3 ( 1%)scheme::VM::run(scheme::Object) [0x8051d90] 1 ( 0%)scheme::VM::run(scheme::Object) [0x8051da4] 1 ( 0%)

VM固有の話

41

VM固有の話

プロファイラではC++の世界しか見えない例えば Mosh なら Scheme の世界を見たい

どの Scheme 手続きが遅いのか?何回呼ばれているのか

41

VM固有の話

プロファイラではC++の世界しか見えない例えば Mosh なら Scheme の世界を見たい

どの Scheme 手続きが遅いのか?何回呼ばれているのか

自前でプロファイラを作ろう意外と簡単

41

プロファイラを作ろう

42

プロファイラを作ろう

プロファイラのやること一定の間隔で実行を割り込み

そのときの「何をしていたか?」を記録

call された関数と回数を記録

42

プロファイラを作ろう

プロファイラのやること一定の間隔で実行を割り込み

そのときの「何をしていたか?」を記録

call された関数と回数を記録

SIGPROFを利用するプロファイラ用のシグナルシグナルハンドラで

「プログラムカウンタ」を記録42

実装

43

struct sigaction act; act.sa_handler = &signal_handler; act.sa_flags = SA_RESTART;

if (sigaction(SIGPROF, &act, NULL) != 0) { callAssertionViolationImmidiaImmediately("profiler", "sigaction failed"); } テキスト startTimer();

void VM::collectProfile(){ static int i = 0; if (!profilerRunning_) return; if (i >= SAMPLE_NUM) { stopTimer(); } else { samples_[i++] = cl_; } totalSampleCount_++;}

シグナルとタイマの設定

シグナルハンドラ

Mosh のプロファイラ

44

time% msec calls name location 27 3510 190 (lambda x y) compiler.scm:8458 8 1140 143356 (lambda i) compiler.scm:9644 8 1110 4039 (pass3/$lambda iform loca...) compiler.scm:9213 7 990 - (<top-level>) 5 650 8456 (pass3/$call iform locals...) compiler.scm:9064 3 500 197791 (lambda s) compiler.scm:9682 2 290 811697 (set-intersect lst1 lst2) compiler.scm:5270 1 220 198 (lambda lst1 lst2) compiler.scm:5249 1 200 2 (lambda x y) compiler.scm:8449 1 190 38872 (lambda i l labels-seen) compiler.scm:8318 1 180 1 (lambda i code) compiler.scm:9072 1 170 42257 (pass1/sexp->iform sexp l...) compiler.scm:7074 1 160 1 (lambda i code) compiler.scm:9072 1 150 197 (lambda x lst) compiler.scm:5246 1 140 215 (lambda i) compiler.scm:8401 1 130 2788 (pass3/$if iform locals f...) compiler.scm:8921 1 130 192 (lambda x lst) compiler.scm:5246

まとめ

45

まとめ

最初にゴールを決めろ

45

まとめ

最初にゴールを決めろ良いデザインを壊すな・測定せよ

45

まとめ

最初にゴールを決めろ良いデザインを壊すな・測定せよグラフを描け

45

まとめ

最初にゴールを決めろ良いデザインを壊すな・測定せよグラフを描け開発プロセスに含めよ

開発測定チューニング

45

宣伝

46

宣伝

Shibuya.lispLisp系言語のコミュニティを立ち上げました10月18日に Tech talk #1 を開催予定http://shibuya.lisp-users.org/

46