1 00:00:00,720 --> 00:00:05,440 Hello, in this course I'll show you how to profile an application in Pharo. 2 00:00:05,600 --> 00:00:08,640 That means measuring the execution of expressions 3 00:00:08,800 --> 00:00:11,320 to see if we can replace them with others to gain time, 4 00:00:11,480 --> 00:00:13,520 during the execution of a program. 5 00:00:14,560 --> 00:00:18,360 Basically, what people say is, if you've never profiled 6 00:00:18,520 --> 00:00:22,920 an application you could increase speeds by 40-50%. 7 00:00:23,080 --> 00:00:26,240 I'm not convinced. I don't know, I've no proof. 8 00:00:26,400 --> 00:00:29,160 But I can show you the tools in Pharo 9 00:00:29,320 --> 00:00:32,160 for doing this profiling. 10 00:00:32,320 --> 00:00:35,800 The first expression in Pharo is "timeToRun". 11 00:00:35,960 --> 00:00:38,320 It's a message we send to a block, 12 00:00:38,480 --> 00:00:40,720 which will give us the run time of an expression. 13 00:00:40,880 --> 00:00:43,680 So, here in "1000 factorial", 14 00:00:43,840 --> 00:00:48,120 I want to measure the run time of "1000 factorial", I put it in a block 15 00:00:48,280 --> 00:00:50,600 and I send the message, "timeToRun". 16 00:00:50,760 --> 00:00:55,120 Now that we have 'timeToRun" it's easy to compare 2 executions. 17 00:00:55,280 --> 00:00:57,520 Here's a little exercise: 18 00:00:57,680 --> 00:01:00,720 If I do "select" followed by "collect", 19 00:01:00,880 --> 00:01:05,280 is it slower than "select:thenCollect", 20 00:01:05,440 --> 00:01:08,400 knowing that this involves two passes 21 00:01:08,560 --> 00:01:10,600 in the first case and one in the second. 22 00:01:10,760 --> 00:01:14,120 So I think it will take longer, but we're going to check. 23 00:01:14,840 --> 00:01:17,560 What do I do? I create my collection in both cases, 24 00:01:17,720 --> 00:01:21,920 I'm looking, I create my collection with 10 elements, a small collection, 25 00:01:22,080 --> 00:01:26,200 and what I'll do is create a certain number of times, 26 00:01:27,360 --> 00:01:31,000 I'll make a loop so I can run the expressions several times. 27 00:01:31,160 --> 00:01:32,960 You can see, in the first part, 28 00:01:33,120 --> 00:01:38,000 I've my collection, I select every element larger than 5, 29 00:01:38,160 --> 00:01:41,920 and afterwards, I'll square the elements I've selected, 30 00:01:42,080 --> 00:01:45,960 and in the 2nd expression, I'll say, what do I want to select? 31 00:01:46,120 --> 00:01:49,840 Everything larger than 5, and I'll square them. 32 00:01:50,000 --> 00:01:53,360 We see that the system tells me that's 500 milliseconds, 33 00:01:53,520 --> 00:01:57,320 and that's 300 milliseconds. The 2nd expression is better. 34 00:01:57,480 --> 00:01:59,960 You see how it works, it's up to you to do it. 35 00:02:00,120 --> 00:02:05,800 Note that we're sometimes obliged to put very large loops inside, 36 00:02:06,560 --> 00:02:11,600 to amplify the measurement, for both cases, of course. 37 00:02:12,080 --> 00:02:16,800 Otherwise, there's another operation, another message called "bench". 38 00:02:16,960 --> 00:02:20,520 "Bench" will tell us how many times the code, 39 00:02:20,680 --> 00:02:26,240 which is being studied, is executed over 5 seconds. 40 00:02:27,560 --> 00:02:31,560 I take my "1000 factorial bench" example again, and I can execute it 41 00:02:31,720 --> 00:02:33,840 610,000 times a second. 42 00:02:34,000 --> 00:02:37,000 In this case, if we so desire, we can also make it 43 00:02:37,160 --> 00:02:39,320 that the figure is as high as possible. 44 00:02:39,480 --> 00:02:42,680 There's also a variant of bench, "benchFor", 45 00:02:42,840 --> 00:02:46,800 where you can specify the size. What's interesting to see 46 00:02:46,960 --> 00:02:50,000 is that "2 seconds", it's really the "second" message, 47 00:02:50,160 --> 00:02:54,920 which is sent to message 2, which will give us a duration, 48 00:02:55,080 --> 00:02:57,480 an instance of the Duration class, 49 00:02:58,120 --> 00:03:01,080 and which will control how long the system runs. 50 00:03:01,240 --> 00:03:04,960 This shows you once again that everything's an object in Pharo. 51 00:03:05,120 --> 00:03:09,240 I set the seconds at 2 seconds. I send the "second" message to object 2. 52 00:03:10,600 --> 00:03:15,080 What you have next, there's also what we call a "profiler", 53 00:03:15,240 --> 00:03:16,880 which is sampling-based. 54 00:03:17,040 --> 00:03:20,520 What will happen is, you'll execute your program, 55 00:03:20,680 --> 00:03:23,880 and it will go at regular intervals 56 00:03:24,040 --> 00:03:26,400 to inspect the execution stack, 57 00:03:26,560 --> 00:03:29,040 see what's in the stack and collect information. 58 00:03:29,200 --> 00:03:33,760 So how do we bring it up? We do "timeProfiler, spyOn" 59 00:03:33,920 --> 00:03:37,800 and we'll pass it a block. I want to repeat 20 times 60 00:03:37,960 --> 00:03:39,680 that I'll show on the Transcript, 61 00:03:39,840 --> 00:03:42,000 "1000 factorial", 62 00:03:42,160 --> 00:03:45,920 which I convert into a string, which usually costs the most. 63 00:03:46,080 --> 00:03:50,480 After that, the profiler will give us this kind of result, 64 00:03:50,640 --> 00:03:55,080 with a tree showing us the branches amongst which we've spent most time. 65 00:03:55,240 --> 00:04:00,000 It shows us we spent 63% of the time in the method "printOn:base". 66 00:04:01,040 --> 00:04:03,240 It's just to show you it's there. 67 00:04:03,400 --> 00:04:06,960 There's a profiler you can play with if you're interested. 68 00:04:07,960 --> 00:04:09,240 So to summarize, 69 00:04:09,480 --> 00:04:10,640 to begin with, 70 00:04:10,800 --> 00:04:14,600 you can use "timeToRun", "bench" and the profiler. 71 00:04:14,760 --> 00:04:19,280 There's a chapter in the book "Deep into Pharo" showing this kind 72 00:04:19,440 --> 00:04:22,560 of optimization technique. 73 00:04:22,720 --> 00:04:26,240 I just wanted to point out, as you see in these 3 examples, 74 00:04:26,400 --> 00:04:30,440 we always use blocks. This is a block... 75 00:04:30,600 --> 00:04:33,400 This is a block too... Why? 76 00:04:33,560 --> 00:04:36,680 You saw in the course on blocks that they allow you 77 00:04:36,840 --> 00:04:39,520 to freeze the expression, the definition of the block 78 00:04:39,680 --> 00:04:42,560 doesn't execute and give "bench" the possibility 79 00:04:42,720 --> 00:04:44,920 of controlling the number of executions 80 00:04:45,080 --> 00:04:48,080 or deciding when execution of the program will begin. 81 00:04:48,240 --> 00:04:50,080 The other thing I'd say is, 82 00:04:50,240 --> 00:04:54,680 find out about how "timeToRun" and "bench" are implemented. 83 00:04:54,840 --> 00:04:57,520 To do that you click on Expression 84 00:04:57,680 --> 00:05:00,840 and do "browse" or "implement" and you'll see the code.