Zero Allocations And Benchmarking In Golang

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is up everyone in this video I'm going to show you how you can Benchmark your code in golang how you can use that to improve existing functions existing programs to check how many allocations we are doing and um because we need to understand that of course we cannot avoid allocations all the time in our program but the last allocations we have the faster or program will run so but before we continue if you're not subscribed to my Channel please consider subscribing give me a thumbs up leave some questions in the comments and jump into my Discord Community alright so I have this file open here in golang it's basically a test file so if you want to make a bench in golang you actually just create a test file the name underscore test.go basically in this case I'm just call it bench test uh because it could be food test bar test whatever as long as you have a test um at the end underscore test at the end of your file right so basically to Benchmark and goal line we can just do Funk uh and then we can say bench normally it would yes it would have a snippet heat so basically uh every function that is prefixed with Benchmark will basically um will be eligible to Benchmark right it's it's that easy no big of a deal so we're gonna say Benchmark uh full or something right we have a testing.b normally we have a testing dot T but in this case we have a testing.b right testing the testing and testing dot Benchmark probably something like that don't really matter right so basically uh for benchmarking we can do it in a couple of ways right so what you would do is basically just make a for Loop here right and in this for Loop instead of this counting we're going to say B Dot N right and B Dot N basically uh is is some kind of thing that's getting injected the number of iterations and all that stuff uh don't worry about it it's just being handled by go itself so basically everything above this function here right is basically an initialization right uh in a solution of the codes right this will not being taken into account of your benchmark everything inside here uh will be actually the bench code right The Benchmark uh code you wanna prefer right so let's take a very very simple example right so let's say we're gonna have uh in this function we're gonna basically create some integers a slice of integers right so we're going to say end and we're going to allocate this uh basically and initialize this slice of integers and of course what am I doing here just like that but we have basically um a non-allocated uh size of integers right so then basically going to Loop right because we're gonna add some integers to it so we're going to look for example let's make heat and a variable we're going to say n is going to be thousand right 100 we're gonna do 100 Loops here right and what we're gonna say is we're going to say that ends equals a pent s and we're going to append y this is basically how I see a lot of people uh doing stuff most of the time you have no option uh but you will see you will see later on hold on right so if we run this Benchmark right we can just click it here in vs code so it's basically going to run this Benchmark and we see some stuff right we see how many nanosexual operation it has how many bytes per operation and then we have basically how many allocations per operation we have and in this case it's going to be eight allocations right so how can we improve this function actually to be honest yeah no let's let's uh take a step by step how can we improve this function right because now we have a message basically what's going on ish um now we have something to measure heat right and it's going to be eight allocs so we know that that's fine right so the next thing you would do actually is uh for example uh make another function you're gonna say benchmark let's call this Benchmark um slash slice not a look right that basically means that we're gonna have a non-allocated slice and in this case we're going to call this Benchmark slice alloc which we're going to have an allocated slice so I'm going to copy this code right and we're going to do it in two manners right you could do it in two ways and I'm gonna show you both so this case uh instead of making this slice Heat this non-allocated slice we're going to basically allocate it pre-allocated slice so we're going to say make me a slice of integers and the length of this is going to be n right because we're going to do one hundred iterations and so we basically can already pre-allocate that with 100 right and then instead of doing this append stuff we're going to say that ends y equals y right that's the thing if we run this we can see that we have only one allocation right so we are basically a lot faster you will see that this this uh time operation and then this bias is going to be it's going to be less right well this I'm not sure but hey don't worry about it right so the the main thing to take away is that we are basically doing less allocation so we are going to be faster at the end right and that's actually very simple uh why is that because we basically do one big allocation of our integer slide so we basically make it as big as 100 so the only thing we need to do is assign that to the memory slots that are already being created under the hood right and in this case we basically just create a slice we don't know how long it's going to be so uh when is there going to be an allocation each time each time the slice needs to grow right it is what it is okay cool so basically uh in this case you can see we have two of these functions here to Benchmark and that's basically a little bit um verbose actually right so we can fix that what we could do is we could say heat uh we can call this testing B heat and we're going to say B run right we can give this a name and I'm gonna call this uh slice uh non-aloc right and then it's gonna take a function closure actually fashion closure and that's going to be a b it's going to be a testing.b right testing.b just like that right and now we can basically copy or code inside of this function just like that right and in this case basically everything here will be in a Cell initialization right well not being taken into account of our Benchmark right so we have this slice and unlock so what we can also do is basically copy this uh B run thingy and we're going to place it here below I'm going to say slice I look and then we're going to copy this code only gonna paste it in heat right so we can delete this just like that boom and maybe some space trim some space hey right so we have this Benchmark slice monologue we could actually rename this to Benchmark slice right and then we have a slice now actually we could do not like the non-alok version and the allocated version to basically compare them uh with each other right if we reach the Benchmark if we wrench If We Run The Benchmark then we can see we have eight allocations each and we have one allocation here and you can see we are a lot faster heat less better operations and of course we have a much more less allocations so or allocated version of our slice is much faster so that's the way to go right that's how you basically Benchmark right so uh how can we actually uh use that to basically um improve code right for example I'm going to make a simple example it's going to be a very short video but very uh Hands-On and very uh direct so we're going to say for example we're going to make a function here and we're going to call that uh right to buffer or something right and we're going to say a message and it's going to be a byte and of course you could return something or hey this is just some pseudo code to give you an ID and what we're going to do is we're going to say once again I recently make a made a video about the bytes buffer right and hey guess what we're going to use it again right bytes perfect is basically my best friend in golang so we're gonna say buffer is going to is going to be a new bytes buffer right and now we're going to say buff right I'm going to write a message to the buffet right so what's what's going to happen is basically we're going to open up a buffet and we're going to write the message into that buffer right and call it a day very simple code of course in real life scenario you're going to do uh some other stuff with that right you're gonna I don't know um hey be creative be creative right so we have this uh right to perfect right so let's make a benchmark I'm gonna say banish Mark uh let's call this right to Buffett or something just like that it's fine then we're gonna say four hop and I'm gonna say it's gonna be a b n right perfectly fine I'm gonna say right to perfect of course a message heat uh two things you could do you could actually put a message in here it's gonna be full or something but you could also make the message uh it's gonna be a slice is going to be full right just like that it doesn't really matter right so let's do MSG like this uh and what you're gonna do basically it's very important because right now you're testing this function once which is not the case we actually wanna um look what we're gonna do is we're gonna make another loopy and we're gonna basically write to buff it to basically prove my point each on how you can actually improve stuff by benchmarking right so uh you need to understand this is basically looping this is basically all uh bench stuff internal internal band stuff right here internal band stuff handled by gulang itself right maybe do a capital G and this is basically Auto logic right or logic is going to be here right and uh why are we looping 100 times because you never know maybe you're basically inside of a connection clients coming in or if you or you're doing some computation and you're basically um recreating this byte's Buffet right that's what I want to want to simulate real quick that we are recreating this bytes perfect right cool so let's run this Benchmark real quick uh right so you can see we have 100 allocations right this is already nasty right we have 100 allocation let me quickly set my coffee because I get right so 100 allocations here and why is that right A lot of people already noticed right so basically we are saying here right to perfect right and we are creating a continuously a new bytes perfect and that's an allocation right so we have 100 Loops so we're gonna have 100 allocations to this by Super Buffet and you could say yeah but that's actually easy but that's uh that's easy to spot but that's not true you would be surprised if you would go to your own code and basically try to uh Benchmark small units of your code you're gonna see sometimes that there are a lot of allocations right and you're gonna say what the hell something you basically uh forgot or something you didn't think about because most of the time you are not thinking about all these uh improvements right because that's a little bit um how technology is going right how it's being educated how it's being tutorialized is that we are building stuff we are building micro Services we are building uh e-commerce websites and all that stuff right and people are basically so focused on how to structure their folders on how to name their variables on how to do authentication all that so that they forgot that there is also something and that is called a performance layer in your application of course it's not the most important well it's a very important layer but it's not the layer that needs to be prioritized right first of all you need to make it work then you need to make it a little bit better and then you can can think about on performance but still performance is important at scale right just want to wanna give you that so basically you want you would be surprised if you were taking small pieces of your code and try to Benchmark it you will see that you uh most of the time well most of the time that most that in some cases you could improve your code a lot uh by reusing stuff and try to minimize allocations right so basically we had this um let's do it again because I'm basically drifting off in this conversation here so we have this 100 allocations why because we're basically creating this bytes perfect uh 100 times right and like I said it could be that you forgot something or you were focused on something else uh but you didn't know right nobody's going to tell you nobody's going to feel it unless you Benchmark it right so how can we fix that well it's very simple we could say hey give me a buffet my keyboard is uh slippy sleepy slippery so we're gonna say actually B for example or Biff it's going to be a bites perfect heat right and actually we need a pointed heat to this thing uh but it's perfect right that's the first thing we can do but is that I don't think so right uh because using a bytes perfectly let's let's actually just do it right we're going to say both right and because we're going to keep refactoring this until it's good right so we have right right to Buffett we're gonna call we're gonna put buffer heat right uh we're gonna make a buffer of course we're going to make that buffer not in our um we're gonna not make it heat and we are not gonna make it here right we're gonna make it completely outside of the benchmarking stuff so we're going to save bites is gonna it's going to be a new uh bytes buffered something like that right and then we basically uh going to yeah it's going to be fine right if we run this real quick yeah you can see we have zero allocations why is that well uh it's because our right to buffer function instead of having 100 allocation you need to understand that this function in the previous test in the previous band bench this function really did want 100 allocations it is what it is and right now we don't do zero allocations right because we have this one bytes buffer that we actually created outside of our bench scope and we will keep writing to that buffer right um of course you could say most of the time you will have one allocation because you're basically going to allocate this byte buffer one more time somewhere in your code but um just want to test this function and this function right now does zero allocation instead of 100 by doing this small improvement improvement right uh next thing I would do basically is not using a bytes buffer I think it's a little bit too strict it's it's a dependency we don't need we're going to say it's going to be an r no actually a w is going to be an i o writer it's going to be an interface right and instead of saying buff right we're going to say w right right the writer is going to write what is going to be that writer we don't care we don't know it's just need to be an i o right right and hey luckily for us uh abides Perfect Isn't IO writer so we don't need to do anything look at this beautiful code so if you run this again then we're gonna see uh we're gonna have zero allocations right it's gonna stay the exact same um do we need to do something else of course you could say right to buffer you could actually do a buff reset here if you really want uh just like that uh so basically this is keep right into the same buffer here right we're gonna keep right into the same writer if you don't want that you can reset the buffet but I think it's going to be fine for now hey that was it very important uh performance is and zero you need to take away that performance is not your priority but it's something that you cannot deny right and you would be surprised how many functions if you're basically trying to Benchmark them uh how many functions you can actually in proof in performance right and if you can do it with one function you can do it with 100 functions and all these little improvements Stack Up In memory better memory management uh in in Faster CPU cycles and all that stuff right so very important to take to uh do that once in a while right do some benchmarks especially if you think it's needed right if you like this video consider subscribing to my channel if you're not already give me a thumbs up leave some questions in the comments and I'm looking forward to see you in one of my live streams are future videos or in my Discord Community peace
Info
Channel: Anthony GG
Views: 7,170
Rating: undefined out of 5
Keywords: golang, golang tutorial, golang for beginners, golang tutorial for beginners, go lang, go programming, go tutorial, go programming language, golang programming, golang tutorials, golang beginner tutorial, golang benchmark, go benchmark, golang testing, go testing, go benchmark tests, golang performance benchmark, go, golang introduction, go language, go programming tutorial, learn golang, go tutorial for beginners, go programming language tutorial
Id: QFGbTOsk-Bk
Channel Id: undefined
Length: 17min 8sec (1028 seconds)
Published: Tue Jan 10 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.