1 00:00:00,720 --> 00:00:05,440 こんにちは、この講義では Pharo での プロファイリングをお見せします。 2 00:00:05,600 --> 00:00:08,640 プロファイリングでは 表現式の実行を計測することで 3 00:00:08,800 --> 00:00:11,320 式を変更して 4 00:00:11,480 --> 00:00:13,520 実行時間を節約できるかを見ます。 5 00:00:14,560 --> 00:00:18,360 基本的に、プロファイリングすることで 6 00:00:18,520 --> 00:00:22,920 実行速度を 40-50% 改善できると 言われています。 7 00:00:23,080 --> 00:00:26,240 実際のところどうなのか ちゃんとした根拠は知りません。 8 00:00:26,400 --> 00:00:29,160 Pharo でプロファイリングをするための 9 00:00:29,320 --> 00:00:32,160 ツールをお見せします。 10 00:00:32,320 --> 00:00:35,800 1つ目の方法は timeToRun という式です。 11 00:00:35,960 --> 00:00:38,320 timeToRun はブロックに送るメッセージで 12 00:00:38,480 --> 00:00:40,720 その式の実行時間を得ることができます。 13 00:00:40,880 --> 00:00:43,680 ここに 1000 factorial がありますが 14 00:00:43,840 --> 00:00:48,120 この 1000 factorial の実行時間を 計測するために、ブロックに入れて 15 00:00:48,280 --> 00:00:50,600 timeToRun メッセージを送ります。 16 00:00:50,760 --> 00:00:55,120 timeToRun を使って 2 つの式の 実行時間を簡単に比較することができます。 17 00:00:55,280 --> 00:00:57,520 簡単な演習問題です。 18 00:00:57,680 --> 00:01:00,720 select: してから collect: すると 19 00:01:00,880 --> 00:01:05,280 select:thenCollect: より遅いかを 20 00:01:05,440 --> 00:01:08,400 知りたいとします。 1 つ目の式は 2 つの段階を経ることになります。 21 00:01:08,560 --> 00:01:10,600 2 つ目の式では 1 段階で済みます。 22 00:01:10,760 --> 00:01:14,120 おそらく前者のほうが時間がかかるでしょう。 いずれにせよ、確認してみましょう。 23 00:01:14,840 --> 00:01:17,560 まずは いずれの場合もコレクションを作ります。 24 00:01:17,720 --> 00:01:21,920 10 要素からなる小さなコレクションです。 25 00:01:22,080 --> 00:01:26,200 そして同じ回数だけ繰り返す 26 00:01:27,360 --> 00:01:31,000 ループを作ります。 27 00:01:31,160 --> 00:01:32,960 1 つ目の式では 28 00:01:33,120 --> 00:01:38,000 コレクションから 5 より大きな要素だけを選んで 29 00:01:38,160 --> 00:01:41,920 それから、選んだ要素の自乗を得ます。 30 00:01:42,080 --> 00:01:45,960 2 つ目の式では 5 より大きな数を選んで 31 00:01:46,120 --> 00:01:49,840 それを自乗しています。 32 00:01:50,000 --> 00:01:53,360 計測すると、それぞれ 500 ミリ秒と 33 00:01:53,520 --> 00:01:57,320 300 ミリ秒かかりました。 2 つ目の式のほうが良いことになります。 34 00:01:57,480 --> 00:01:59,960 これで、やり方はわかったので あとはあなた次第です。 35 00:02:00,120 --> 00:02:05,800 ただ、計測結果を大きくするために 36 00:02:06,560 --> 00:02:11,600 両方の場合についてとても大きなループを いれなければならないこともあります。 37 00:02:12,080 --> 00:02:16,800 別の方法として bench メッセージがあります。 38 00:02:16,960 --> 00:02:20,520 bench メッセージで 5 秒の間に 39 00:02:20,680 --> 00:02:26,240 そのコードが何回実行できるのかを計測します。 40 00:02:27,560 --> 00:02:31,560 再び 1000 factorial を例にすると 41 00:02:31,720 --> 00:02:33,840 1 秒で 610 回実行できます。 42 00:02:34,000 --> 00:02:37,000 bench メッセージの場合には 改善するためには 43 00:02:37,160 --> 00:02:39,320 数字が大きな方が良いことになります。 44 00:02:39,480 --> 00:02:42,680 bench のバリエーションとして benchFor: で 45 00:02:42,840 --> 00:02:46,800 計測時間を指定することができます。 46 00:02:46,960 --> 00:02:50,000 ここに 2 seconds とありますが これは seconds メッセージで 47 00:02:50,160 --> 00:02:54,920 2 に送られて 期間(時間幅)が得られます。 48 00:02:55,080 --> 00:02:57,480 Duraction クラスのインスタンスです。 49 00:02:58,120 --> 00:03:01,080 これでシステムが計測する時間を 操ることができます。 50 00:03:01,240 --> 00:03:04,960 これもまた Pharo では全てがオブジェクトだ という実例です。 51 00:03:05,120 --> 00:03:09,240 オブジェクト 2 に seconds メッセージを送って 計測時間を 2 秒にセットします。 52 00:03:10,600 --> 00:03:15,080 次にプロファイラーをお見せします。 53 00:03:15,240 --> 00:03:16,880 プロファイラーはサンプリングによるものです。 54 00:03:17,040 --> 00:03:20,520 プログラムを実行して 55 00:03:20,680 --> 00:03:23,880 一定間隔で 56 00:03:24,040 --> 00:03:26,400 実行スタックを調べて 57 00:03:26,560 --> 00:03:29,040 情報を集めます。 58 00:03:29,200 --> 00:03:33,760 これを使うには TimeProfiler spyOn: を使って 59 00:03:33,920 --> 00:03:37,800 ブロックを渡します。 20 回繰り返して 60 00:03:37,960 --> 00:03:39,680 1000 factorial を計算して 61 00:03:39,840 --> 00:03:42,000 結果をTranscript に表示します。 62 00:03:42,160 --> 00:03:45,920 ここで通常は文字列への変換が 最もコストがかかります。 63 00:03:46,080 --> 00:03:50,480 そしてプロファイラーが このように結果を 64 00:03:50,640 --> 00:03:55,080 木構造でどの部分が最も時間がかかったかを 表示します。 65 00:03:55,240 --> 00:04:00,000 今回は、実行時間の 63% が printOn:base: に費やされました。 66 00:04:01,040 --> 00:04:03,240 こんな風にプロファイラーを 67 00:04:03,400 --> 00:04:06,960 使うことができるということです。 68 00:04:07,960 --> 00:04:09,240 まとめると 69 00:04:09,480 --> 00:04:10,640 まずは 70 00:04:10,800 --> 00:04:14,600 timeToRun: や bench や プロファイラーを使うことができます。 71 00:04:14,760 --> 00:04:19,280 書籍「Deep into Pharo」では 1 つの章をつかって 72 00:04:19,440 --> 00:04:22,560 この種の最適化技法を説明しています。 73 00:04:22,720 --> 00:04:26,240 ここで大事なことは これら 3 つの例の 74 00:04:26,400 --> 00:04:30,440 いずれもブロックを使うということです。 これもブロック 75 00:04:30,600 --> 00:04:33,400 これもまたブロックです。なぜでしょう? 76 00:04:33,560 --> 00:04:36,680 このコースの中で ブロックをつかって 77 00:04:36,840 --> 00:04:39,520 表現式を凍結することを学びました。 ブロックを定義することは 78 00:04:39,680 --> 00:04:42,560 そのまま実行することではありません。 bench メッセージが 79 00:04:42,720 --> 00:04:44,920 実行回数を制御することができ 80 00:04:45,080 --> 00:04:48,080 また、その式をいつ実行開始するかを 決めることができるのです。 81 00:04:48,240 --> 00:04:50,080 もう 1 つ 82 00:04:50,240 --> 00:04:54,680 timeToRun や bench がどう実装されているか 探してみてください。 83 00:04:54,840 --> 00:04:57,520 表現式の上でクリックして 84 00:04:57,680 --> 00:05:00,840 インプリメンター(implementors)で コードを見ることができます。