WEBVTT 0 00:02.860 --> 00:03.760 Welcome back! 1 00:03.790 --> 00:09.370 As I've promised in the last lecture, now, I'm going to show you how to add a buffer to optimize the program. 2 00:10.000 --> 00:10.590 Let's get started! 3 00:14.060 --> 00:16.070 When I call a Print function, 4 00:16.130 --> 00:20.580 it needs to talk to the Operating System, and that is an expensive operation. 5 00:21.200 --> 00:26.530 So, instead of doing it like so, I'm going to draw the board to a buffer first, and then I'm going 6 00:26.530 --> 00:29.180 to print the buffer once on each loop. 7 00:29.600 --> 00:35.500 So basically I will be drawing the board into the memory. After each loop step, 8 00:35.630 --> 00:41.360 I will need to reuse the same buffer as well, or using a buffer would be meaningless. 9 00:41.360 --> 00:46.230 It's because creating a buffer also takes time. Remember, 10 00:46.360 --> 00:47.880 I need to draw images. 11 00:48.040 --> 00:50.510 So I need a rune slice as a buffer. 12 00:50.680 --> 00:58.270 I can do so using the make function because I know the exact capacity of my buffer. I've multiplied the 13 00:58.270 --> 01:04.500 width by height because I want my buffer to include every cell in my buffer. 14 01:04.630 --> 01:06.730 I'm only going to append to the buffer, 15 01:06.820 --> 01:10.970 so that's why I have declared the single dimensional slice. 16 01:11.080 --> 01:17.910 If I had declared a multidimensional slice, I would need to initialize each one of the inner slices. 17 01:17.920 --> 01:21.730 However, in this case, I use a single dimensional slice. 18 01:21.820 --> 01:25.880 So I can initialize it using the make function only once. 19 01:26.260 --> 01:34.270 So why I use a multidimensional bool slice for the board? It's because, in that case, I'm going to access 20 01:34.270 --> 01:35.560 the inner elements. 21 01:35.680 --> 01:41.150 So using a multidimensional slice makes it easier to work with. Anyways. 22 01:41.320 --> 01:45.720 So as you can see, in this case, a buffer is just a slice. 23 01:45.790 --> 01:52.090 I'm going to reuse this slice after I draw it to the screen. Now I need to fill the buffer, instead of 24 01:52.090 --> 01:59.240 calling the print functions. Let me first comment out the first print call here. Then, I'm going to add 25 01:59.360 --> 02:03.230 the current cell value, and the space character into the buffer instead. 26 02:06.220 --> 02:08.020 Here, I print a new line. 27 02:08.050 --> 02:16.290 So instead of this, let me add a new line character into the buffer, like so. Okay now it's time to print 28 02:16.290 --> 02:23.860 the buffer to the screen like so. Why does it print a lot of numbers? 29 02:23.870 --> 02:29.720 The answer is that the buffer is a rune slice. Remember a rune is a numeric type. 30 02:30.110 --> 02:34.070 So a rune slice is actually a bunch of numbers. 31 02:34.220 --> 02:38.220 As I said, numbers can be converted to string values. 32 02:38.240 --> 02:42.710 So now I'm going to convert the buffer into a string value like so. 33 02:46.230 --> 02:48.150 Cool! It works. 34 02:48.210 --> 02:51.630 You'll learn more about the numbers and strings later on. 35 02:51.630 --> 02:57.670 No worries. OK, so what is the benefit of using a buffer? 36 02:57.690 --> 03:01.200 Let me show you how to measure the performance of this program. 37 03:01.500 --> 03:07.620 So you can better understand the benefits of using a buffer. However, measuring the current program won't 38 03:07.620 --> 03:12.510 give us enough data because the current program doesn't do anything much. 39 03:12.570 --> 03:19.920 We need to see the real performance optimization between a buffer and a non-buffered approach. 40 03:19.920 --> 03:21.120 So what should I do? 41 03:21.840 --> 03:24.430 Well I can exercise the current program 42 03:24.480 --> 03:31.620 a lot of times to get a meaningful measurement using a loop like so. If you're using a bash command prompt 43 03:31.680 --> 03:34.990 you can measure your program by using the time command. 44 03:35.120 --> 03:37.320 If you're not using a bash prompt, 45 03:37.320 --> 03:42.540 check out the link in the resources to find an alternative, if you're using Windows and not using a bash 46 03:42.540 --> 03:44.350 prompt. 47 03:44.430 --> 03:49.930 Let's assume that you're using a bash command prompt, so you just need to call "time". 48 03:50.130 --> 03:54.520 Then as an argument you need to pass it the command that you want to execute. 49 03:54.540 --> 03:58.560 In my case it is an ordinary "go run main.go". 50 03:58.590 --> 04:04.390 Lastly, you need to redirect the output of the program to the null device. 51 04:04.470 --> 04:07.410 Actually, this last step is not necessary. 52 04:07.410 --> 04:14.520 If you don't redirect the output it is going to print the smiley face hundreds of times to the console. 53 04:14.520 --> 04:22.760 Try it and you'll see what I mean. As you can see, the time program prints a few details about how much 54 04:22.760 --> 04:29.600 time it takes to complete, and how much time it spends in the user mode, and in the kernel mode. 55 04:29.690 --> 04:35.720 For now, I'm only interested in the total compilation time because that is what I'm trying to optimize 56 04:35.720 --> 04:42.440 for, right. Now. let me change the program, so that it won't use a buffer, and instead it will print directly. 57 04:46.030 --> 04:47.560 All right! Let's try it. 58 04:51.680 --> 04:57.790 Interestingly, it looks like our buffered approach is much slower than a non-buffered approach. 59 04:57.860 --> 05:05.450 However, I think we have made a mistake somewhere. In my experience using a buffer in this situation should 60 05:05.450 --> 05:08.690 have made the program faster but it didn't. 61 05:08.690 --> 05:12.810 So let's find out what's wrong with our buffered program. 62 05:12.900 --> 05:15.080 Let me make the program use the buffer again. 63 05:16.740 --> 05:20.090 I think I have found the problem here. Can you also see it? 64 05:20.310 --> 05:22.410 Please pause the video and think about it. 65 05:26.680 --> 05:32.980 OK, the problem is that the append calls allocate a lot of backing arrays unnecessarily, and this is the 66 05:32.980 --> 05:35.800 reason behind the slowness of the program. 67 05:35.800 --> 05:42.240 After each loop step, I need to use the same buffer again, or using a buffer here doesn't make a sense. 68 05:42.700 --> 05:46.710 I can do so by reducing the length of the buffer to 0, 69 05:46.720 --> 05:47.230 like so. 70 05:47.890 --> 05:54.520 So the append calls will use the previous buffer, so they won't cause allocating new backing arrays. They 71 05:54.520 --> 05:56.710 will start from the first element. 72 05:56.860 --> 06:00.400 If you don't remember how the append and backing arrays work, 73 06:00.400 --> 06:02.860 please watch the slice internals lectures. 74 06:08.030 --> 06:12.440 As you can see, now the program is faster than the non-buffered version. 75 06:12.560 --> 06:19.160 So, in summary, when you call the Print functions directly they need to talk to the operating system, and 76 06:19.160 --> 06:25.430 doing so is expensive because the program spends a lot of its time talking to the Operating System, and 77 06:25.430 --> 06:32.920 waiting for a response. However, if you forget reusing the same buffer, that is worse than not using 78 06:32.920 --> 06:34.190 a buffer at all. 79 06:34.570 --> 06:39.720 By the way, the loop here was for the measuring the execution time better. 80 06:39.760 --> 06:45.490 I don't need it anymore, so I'm going to remove it. As you'll see in the next lecture that I'm gonna add 81 06:45.490 --> 06:46.340 it back again. 82 06:46.360 --> 06:48.700 But not for measuring the execution type, 83 06:48.700 --> 06:51.250 I'll do it for animating the bouncing ball. 84 06:51.490 --> 06:52.930 All right, that's all for now. 85 06:52.960 --> 06:58.240 This is not the only way to measure the efficiency of this program but it's one of the easiest ways. 86 06:58.270 --> 06:58.920 All right. 87 06:58.960 --> 07:01.000 In the next lecture I'm going to animate the ball. 88 07:01.000 --> 07:01.500 See you there.