﻿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）で
コードを見ることができます。
