WEBVTT 00:00.000 --> 00:10.000 Hello everyone, thank you for coming to my talk. 00:10.000 --> 00:13.000 If it isn't obvious enough, it's going to be about generics. 00:13.000 --> 00:16.000 I'm Anton, I'm based in Bulgaria. 00:16.000 --> 00:19.000 I'm a senior software engineer at Castellai, 00:19.000 --> 00:22.000 where I'm working on making your Kubernetes closer to more secure. 00:22.000 --> 00:25.000 I've been doing go-sings around 2019, 00:25.000 --> 00:27.000 and before that I was doing Java, 00:27.000 --> 00:31.000 and I think my time spent working put JavaScript consciously contributed 00:31.000 --> 00:32.000 to my love for generics, 00:32.000 --> 00:37.000 and it's the reason why I chose this topic for today's talk. 00:37.000 --> 00:39.000 You can follow me in social media, 00:39.000 --> 00:41.000 so let's get started. 00:41.000 --> 00:44.000 So what are generics? 00:44.000 --> 00:48.000 Well, it's just a way of programming that allows you to write code 00:48.000 --> 00:51.000 which works with multiple types, while still preserving types, 00:51.000 --> 00:54.000 and they were introduced in GoFerry recently 00:54.000 --> 00:58.000 in Go1.18, which came out in 2022. 00:58.000 --> 01:01.000 So how many of you have actually worked with generics? 01:01.000 --> 01:06.000 Like, written a generic function, or use some library that has had generics. 01:06.000 --> 01:09.000 So, okay, quite a few hints. 01:09.000 --> 01:14.000 Yeah, I'm still going to do a very quick introduction to generics. 01:14.000 --> 01:15.000 This is a generic function. 01:15.000 --> 01:17.000 It looks like a regular function, 01:17.000 --> 01:19.000 but here in the square brackets, 01:19.000 --> 01:22.000 we have this section what makes a function generic. 01:22.000 --> 01:24.000 We define here the generic type t, 01:24.000 --> 01:28.000 and we give it a type constraint, which limits what this type can actually be. 01:28.000 --> 01:32.000 And then in the body we have a regular code that uses this type. 01:32.000 --> 01:34.000 So, with the time of writing this function, 01:34.000 --> 01:36.000 we don't know what this type t is. 01:36.000 --> 01:38.000 We only know that when we start using it. 01:38.000 --> 01:40.000 And we use it like this. 01:40.000 --> 01:43.000 Here, recalling this function twice, 01:43.000 --> 01:46.000 once with integer arguments and one with floating point numbers, 01:46.000 --> 01:49.000 and you see the arguments, they match the type of, 01:49.000 --> 01:51.000 we define here. 01:51.000 --> 01:53.000 Also, the compiler is pretty smart, 01:53.000 --> 01:55.000 so we don't need to actually give it a type. 01:55.000 --> 01:57.000 It can infer it by itself. 01:57.000 --> 01:59.000 In this case, this is still an integer function, 01:59.000 --> 02:03.000 and our result will still be size of integers. 02:03.000 --> 02:05.000 And if you want to do something stupid like this, 02:05.000 --> 02:07.000 the compiler will scream at us. 02:07.000 --> 02:09.000 It will not let us write this code because 02:09.000 --> 02:11.000 these two things here are different types. 02:11.000 --> 02:13.000 So, we cannot use them with this function, 02:13.000 --> 02:17.000 because we require the type to be the same. 02:17.000 --> 02:19.000 And this is basically the gist of it. 02:19.000 --> 02:22.000 A little bit of history on how we got here. 02:22.000 --> 02:24.000 I guess most of you know, 02:24.000 --> 02:27.000 go was released in 2009 in November, 02:27.000 --> 02:28.000 with this blog post. 02:28.000 --> 02:30.000 It was internally developed in Google, 02:30.000 --> 02:32.000 shortly before that. 02:32.000 --> 02:35.000 And in 2009, they released it to the world. 02:35.000 --> 02:39.000 So, why did they actually create a new language in 2009? 02:39.000 --> 02:41.000 There were a lot of languages already in the wild, 02:41.000 --> 02:43.000 so why create a new one? 02:43.000 --> 02:46.000 Well, at that time, Google was using a lot of C++, 02:47.000 --> 02:49.000 so they had a big C++ code base. 02:49.000 --> 02:51.000 And one thing with C++, 02:51.000 --> 02:52.000 it's a very powerful language, 02:52.000 --> 02:54.000 but it's also very complex one. 02:54.000 --> 02:55.000 So, you can do a lot of stuff, 02:55.000 --> 02:58.000 and the complexity can get quite high. 02:58.000 --> 03:01.000 So, for example, for the end of the scatter to onboard new people, 03:01.000 --> 03:03.000 especially in more junior ones, 03:03.000 --> 03:04.000 to their complex code base, 03:04.000 --> 03:06.000 that's why they wanted to have a new language, 03:06.000 --> 03:07.000 which is more simple. 03:07.000 --> 03:09.000 So, what it is years to onboard new people. 03:09.000 --> 03:13.000 Also, C++ is notorious for its slow compilation times. 03:13.000 --> 03:15.000 So, they wanted a new language, 03:15.000 --> 03:16.000 not as well. 03:16.000 --> 03:19.000 But they very much liked how fast C++ runs, 03:19.000 --> 03:23.000 so they wanted to keep this in a new language that they created. 03:23.000 --> 03:25.000 And that's how it came to be. 03:25.000 --> 03:29.000 However, it turns out that genetics kind of complicate 03:29.000 --> 03:31.000 each one of these three conditions. 03:31.000 --> 03:34.000 So, back then in 2009, it kind of makes sense 03:34.000 --> 03:36.000 that to not have genetics in the language. 03:36.000 --> 03:40.000 However, it took them less than 24 hours 03:40.000 --> 03:42.000 for people with the internet to start complaining 03:42.000 --> 03:44.000 about the lack of genetics. 03:44.000 --> 03:46.000 Yeah, this is a Google group, 03:46.000 --> 03:48.000 a discussion about the language, 03:48.000 --> 03:50.000 and you see, this is November 11th. 03:50.000 --> 03:52.000 So, one day after the language was released, 03:52.000 --> 03:55.000 someone complaining that the language doesn't have genetics. 03:55.000 --> 03:58.000 And this kind of set the tone of how the next few years 03:58.000 --> 03:59.000 are going to, 03:59.000 --> 04:02.000 the combined people will continue complaining about the lack of genetics. 04:02.000 --> 04:04.000 It's always going to be one of the most requested features 04:04.000 --> 04:06.000 to be able to the language. 04:06.000 --> 04:08.000 So, what did the goal team do about that? 04:08.000 --> 04:10.000 It turns out they did quite a lot. 04:10.000 --> 04:13.000 So, one year later, we got the first proposal for genetics. 04:13.000 --> 04:15.000 It was called type functions. 04:15.000 --> 04:16.000 It was rejected. 04:16.000 --> 04:18.000 Obviously, then we had another one. 04:18.000 --> 04:21.000 2011 called generalized types. 04:21.000 --> 04:24.000 Then we had two more in 2013 called type parameters 04:24.000 --> 04:26.000 and generalized types V2. 04:26.000 --> 04:29.000 As you know, all the more rejected. 04:29.000 --> 04:32.000 All four of those proposals came from within the goal team. 04:32.000 --> 04:35.000 And the majority of work was done by one guy. 04:35.000 --> 04:37.000 He was called Ian Lansteuer. 04:37.000 --> 04:40.000 So, yeah, this effort came from the goal team itself. 04:41.000 --> 04:44.000 Then we had some radio silence on the topic. 04:44.000 --> 04:47.000 But in 2018 and 2019, we got two more proposals 04:47.000 --> 04:49.000 called contracts and contracts V2. 04:49.000 --> 04:54.000 Essentially, this, we got one more in 2021. 04:54.000 --> 04:55.000 Type parameters. 04:55.000 --> 04:58.000 And this is actually the proposal that got accepted. 04:58.000 --> 05:01.000 And these three proposals, they were still written by the same guy 05:01.000 --> 05:02.000 from before. 05:02.000 --> 05:05.000 So, yeah. 05:05.000 --> 05:07.000 Finally, he got his way in. 05:07.000 --> 05:09.000 We got genetics. 05:09.000 --> 05:13.000 So, what took them so long? 05:13.000 --> 05:15.000 Obviously, the goal team wants to do that. 05:15.000 --> 05:17.000 All these proposals came from within the goal team. 05:17.000 --> 05:19.000 The community also wanted to hear that. 05:19.000 --> 05:21.000 So, what took them so long? 05:21.000 --> 05:25.000 I think, last of this question, we had to get back to this book post 05:25.000 --> 05:26.000 by Roscox. 05:26.000 --> 05:28.000 It's from December 2009. 05:28.000 --> 05:30.000 So, this is the first month of the language. 05:30.000 --> 05:32.000 And it's called the genetic dilemma. 05:32.000 --> 05:35.000 What it says in this article, it's basically, 05:35.000 --> 05:38.000 he came to the conclusion that the genetic dilemma is, 05:38.000 --> 05:41.000 do we want slow programmers, slow compilers, 05:41.000 --> 05:43.000 or slow execution times? 05:43.000 --> 05:47.000 So, what Roscox did was he looked at all these other languages 05:47.000 --> 05:49.000 that already existed back then. 05:49.000 --> 05:52.000 And he looked at how they implemented genetics. 05:52.000 --> 05:55.000 And he realized that if you want genetics or don't want genetics, 05:55.000 --> 05:59.000 you'll need to choose one of three trade-offs. 05:59.000 --> 06:03.000 He basically came up with three categories of languages. 06:03.000 --> 06:06.000 The first one is languages like C, but don't have genetics, 06:06.000 --> 06:10.000 so you don't have the productivity boost that feature 06:10.000 --> 06:11.000 like genetics give you. 06:11.000 --> 06:14.000 But you do have fast compilers and fast run times. 06:14.000 --> 06:17.000 Then you have C++, where you do have genetics, 06:17.000 --> 06:19.000 and you do have the fast run time, 06:19.000 --> 06:21.000 but you have to get the slow compilation time 06:21.000 --> 06:23.000 because of the way genetics are implemented. 06:23.000 --> 06:27.000 And then you have Java, where, again, you have fast programmers, 06:27.000 --> 06:29.000 you have fast compilers, 06:29.000 --> 06:31.000 but because of the way genetics are implemented, 06:31.000 --> 06:34.000 which is completely different than C++, 06:34.000 --> 06:36.000 you get the performance heating in runtime. 06:36.000 --> 06:38.000 And having in mind that, 06:38.000 --> 06:41.000 go already did have limited support for genetics 06:41.000 --> 06:45.000 for the building types, like maps, slices, channels. 06:45.000 --> 06:49.000 I guess they just didn't want to do to take any one of these three trade-offs 06:49.000 --> 06:52.000 and just decided to leave the things as they are. 06:52.000 --> 06:56.000 But as we show, we already have an accepted proposal. 06:56.000 --> 06:58.000 And now let's talk about the implementation. 06:58.000 --> 07:00.000 Let's see what this proposal tells us about 07:00.000 --> 07:03.000 how genetics are going to be implemented and go. 07:03.000 --> 07:06.000 Well, it didn't tell us anything. 07:06.000 --> 07:09.000 The final proposal and also all the previous one, 07:09.000 --> 07:11.000 in their implementation paragraph, 07:11.000 --> 07:14.000 they say, we are aware of the genetics dilemma. 07:14.000 --> 07:16.000 We don't want to take a decision on this. 07:16.000 --> 07:19.000 The proposal is flexible enough, so that you can implement it 07:19.000 --> 07:20.000 however you like. 07:20.000 --> 07:22.000 So, basically, it doesn't give us any any guys on how 07:22.000 --> 07:24.000 it's going to be implemented. 07:24.000 --> 07:25.000 So, what do we do? 07:25.000 --> 07:29.000 We need to write more proposals for the actual implementation. 07:30.000 --> 07:33.000 In reality, there were three proposals written for the implementation. 07:33.000 --> 07:35.000 The final one was accepted, 07:35.000 --> 07:40.000 but for us to better understand how we came to how we came there. 07:40.000 --> 07:44.000 We need to look at all three other proposals. 07:44.000 --> 07:47.000 The first one is called stenciling, 07:47.000 --> 07:50.000 and this is basically the simplest way of doing things. 07:50.000 --> 07:53.000 And stenciling means that when we have a genetic function, 07:53.000 --> 07:55.000 and we use it with some types, 07:55.000 --> 07:58.000 we're going to compile one function for all the types 07:58.000 --> 08:00.000 that we use our genetic function with. 08:00.000 --> 08:02.000 Let's see an example. 08:02.000 --> 08:04.000 On the left, we have a genetic code, 08:04.000 --> 08:07.000 pretty simple function that just takes two values, 08:07.000 --> 08:10.000 and turns the sum of them. 08:10.000 --> 08:13.000 And we are calling it with first with integers, 08:13.000 --> 08:15.000 and then with floating point numbers. 08:15.000 --> 08:17.000 What we have done during compilation is that the compiler 08:17.000 --> 08:20.000 will actually produce two functions. 08:20.000 --> 08:23.000 The first one we work with just integers, 08:23.000 --> 08:26.000 the second one we work with just floats. 08:26.000 --> 08:30.000 And on the cosite, we're going to replace the genetic function 08:30.000 --> 08:33.000 with the specific implementation of this function for this type. 08:33.000 --> 08:35.000 Of course, this is just pure code. 08:35.000 --> 08:38.000 The go compiler doesn't produce any go code. 08:38.000 --> 08:39.000 It produces machine code, 08:39.000 --> 08:42.000 but it's just on illustration of how this is going 08:42.000 --> 08:45.000 to look like according to the proposal. 08:45.000 --> 08:47.000 So yeah, this is done. 08:47.000 --> 08:51.000 This is the implementation and the floating presentation. 08:51.000 --> 08:55.000 The big benefits here are that you basically don't have any performance 08:55.000 --> 08:57.000 during any performance penalty during current time, 08:57.000 --> 08:59.000 because in current time you don't have genetic functions. 08:59.000 --> 09:01.000 We have regular functions. 09:01.000 --> 09:04.000 However, the performance hits come during compilation. 09:04.000 --> 09:06.000 Now the compiler has to do a lot more work 09:06.000 --> 09:09.000 to compile this function multiple times for each other types 09:09.000 --> 09:10.000 that we work with. 09:10.000 --> 09:13.000 And this also contributes to the bigger binary size, 09:13.000 --> 09:16.000 because now we have more stuff in our compiled binary. 09:16.000 --> 09:20.000 So because of these reasons, this proposal was rejected. 09:20.000 --> 09:23.000 The second proposal is called dictionaries, 09:23.000 --> 09:26.000 and this is more or less the way Java does scenarios. 09:26.000 --> 09:30.000 This says we're going to compile a single function 09:30.000 --> 09:32.000 for the generic function. 09:32.000 --> 09:35.000 And we're going to use dictionaries to keep all the type information 09:35.000 --> 09:39.000 for the specific types that we use our function with. 09:39.000 --> 09:41.000 Let's see how this looks like. 09:41.000 --> 09:45.000 Again, we have the same simple function. 09:45.000 --> 09:48.000 And after compilation, this looks like this. 09:48.000 --> 09:51.000 Now you see on the left, we have just a single implementation 09:51.000 --> 09:53.000 of our same diff function. 09:53.000 --> 09:56.000 And we see here are two arguments A and B, 09:56.000 --> 09:59.000 but now they are just pointers. 09:59.000 --> 10:02.000 And the return value is also pointer. 10:02.000 --> 10:04.000 But we also see we have one more argument 10:04.000 --> 10:06.000 that's being connected to our function, 10:06.000 --> 10:09.000 and this is this thing here, the dictionary. 10:09.000 --> 10:11.000 And this here contains all the type information 10:11.000 --> 10:14.000 for the types that we are using this function with. 10:14.000 --> 10:16.000 You see on the top, we have the type, 10:16.000 --> 10:20.000 and it also like all the functions that are present on these types. 10:20.000 --> 10:22.000 We have the introduction dictionary as well. 10:22.000 --> 10:24.000 In this case, the data function 10:24.000 --> 10:27.000 substitutes the plus operator. 10:27.000 --> 10:30.000 What happens when we call such function, 10:30.000 --> 10:34.000 you see here, we are calling it with two integers. 10:34.000 --> 10:38.000 The compiler now needs to box these values into pointers. 10:38.000 --> 10:42.000 And it needs to come up with this dictionary 10:42.000 --> 10:44.000 that provides implementation. 10:44.000 --> 10:46.000 And you see in the implementation, we actually need to 10:46.000 --> 10:48.000 unbox these values to get there, 10:48.000 --> 10:50.000 to get there actually with your values. 10:50.000 --> 10:51.000 We need to sum them, 10:51.000 --> 10:54.000 and then we need to box this again into a pointer 10:54.000 --> 10:55.000 to enter and return it. 10:55.000 --> 10:57.000 And here we need to unbox that, 10:57.000 --> 11:01.000 that return value again to get the actual value. 11:01.000 --> 11:04.000 This doesn't have a big performance penalty 11:04.000 --> 11:06.000 in compilation time. 11:06.000 --> 11:08.000 Yes, the compiler does more work, 11:08.000 --> 11:10.000 but we can say it's negligible. 11:10.000 --> 11:13.000 However, the big penalty here comes during runtime. 11:13.000 --> 11:16.000 Because all this referencing can be referencing, 11:16.000 --> 11:18.000 it just adds some overhead, 11:18.000 --> 11:20.000 and it makes our code run slower. 11:20.000 --> 11:23.000 Also, it kind of prevents compiler inlining, 11:23.000 --> 11:26.000 because now, what's the information is not present 11:26.000 --> 11:29.000 in compile time is present on it runtime. 11:29.000 --> 11:32.000 So this prevents the compiler from inlining our stuff. 11:32.000 --> 11:34.000 And I'm not an expert in compilers, 11:34.000 --> 11:37.000 but I know that this is generally a good thing inlining. 11:37.000 --> 11:39.000 And when we're using this approach, 11:39.000 --> 11:42.000 we are preventing the compiler from doing this nice optimization for us. 11:42.000 --> 11:46.000 So we can say we get a big performance here in runtime. 11:46.000 --> 11:50.000 And this is why this proposal will reject it. 11:50.000 --> 11:53.000 So we can enter a third proposal, 11:53.000 --> 11:55.000 which is called gc shape stenciling. 11:55.000 --> 11:57.000 This is the proposal that actually got accepted. 11:57.000 --> 11:59.000 And this is more or less the middle ground 11:59.000 --> 12:01.000 between the first two proposals. 12:01.000 --> 12:03.000 So they said stenciling is bad, 12:03.000 --> 12:06.000 dictionaries are bad, let's do both. 12:07.000 --> 12:13.000 Yeah, so as I said, this is the middle ground. 12:13.000 --> 12:15.000 So we do this a little bit of stenciling, 12:15.000 --> 12:16.000 and a little bit of dictionaries. 12:16.000 --> 12:18.000 And actually what it does is, 12:18.000 --> 12:23.000 it this produced multiple versions of our functions, 12:23.000 --> 12:26.000 but only for types that have different representation in memory. 12:26.000 --> 12:28.000 This is what gc shape stands for, 12:28.000 --> 12:30.000 garbage collector shape. 12:30.000 --> 12:33.000 So functions, types that have the same memory representation, 12:34.000 --> 12:37.000 we get the same representation of the generic function, 12:37.000 --> 12:40.000 and the type information we present in these dictionaries. 12:40.000 --> 12:43.000 This is the proposal that got accepted. 12:43.000 --> 12:45.000 So how this looks like? 12:45.000 --> 12:47.000 I have here still a simple example, 12:47.000 --> 12:49.000 although different in the previous one. 12:49.000 --> 12:52.000 I have a generic function called pint and return. 12:52.000 --> 12:54.000 It accepts type t, 12:54.000 --> 12:56.000 which needs to satisfy the stringer interface. 12:56.000 --> 12:59.000 It gets the value of the string. 12:59.000 --> 13:02.000 It brings it and it just returns the value t. 13:03.000 --> 13:06.000 Please keep it function, but it works for an example. 13:06.000 --> 13:08.000 And I'm calling this function four times, 13:08.000 --> 13:10.000 four times with four different types. 13:10.000 --> 13:11.000 First time with an integer, 13:11.000 --> 13:13.000 then with a string, 13:13.000 --> 13:15.000 they are wrapped into their own custom type 13:15.000 --> 13:18.000 so that we can provide the string implementation. 13:18.000 --> 13:21.000 And then with two structs, A and B, 13:21.000 --> 13:24.000 which I am passing as pointers. 13:24.000 --> 13:27.000 So let's see how this looks like after compilation. 13:27.000 --> 13:29.000 But now we don't need to look at pseudocard 13:29.000 --> 13:31.000 because this is the actual implementation of generics. 13:31.000 --> 13:33.000 So we can do something better. 13:33.000 --> 13:34.000 While I did, 13:34.000 --> 13:36.000 I compiled this code. 13:36.000 --> 13:38.000 I gave it some 13:38.000 --> 13:41.000 compiler flags to prevent optimizations and inlining. 13:41.000 --> 13:44.000 And then I used the go-to object dump command 13:44.000 --> 13:47.000 to do the sample executed by the go-view. 13:47.000 --> 13:50.000 And we can actually look at some of the sample code. 13:50.000 --> 13:53.000 This is how it looks like. 13:53.000 --> 13:55.000 On the right is this a demo code 13:55.000 --> 13:58.000 and we see the shapes of the compiler produced. 13:58.000 --> 14:02.000 So we see our function was compiled three times. 14:02.000 --> 14:05.000 But why three times if we call it four different types? 14:05.000 --> 14:07.000 Well because A and B, 14:07.000 --> 14:08.000 they are just pointers. 14:08.000 --> 14:10.000 So they have the same memory representation. 14:10.000 --> 14:12.000 They are just a u in date. 14:12.000 --> 14:19.000 So the compiler compiled only one shape for these two types. 14:19.000 --> 14:24.000 Let's dive into the implementation of this function. 14:25.000 --> 14:27.000 Yeah, this is for the integer. 14:27.000 --> 14:30.000 You see here go shape int. 14:30.000 --> 14:33.000 This indicates that this is for the integer. 14:33.000 --> 14:35.000 Then you have the string. 14:35.000 --> 14:38.000 Here for the string value. 14:38.000 --> 14:41.000 And then you have the u in date for the pointers. 14:41.000 --> 14:45.000 So let's dive into that function. 14:45.000 --> 14:48.000 So let's see what happens. 14:48.000 --> 14:50.000 What happens inside. 14:50.000 --> 14:52.000 We see here in the beginning. 14:52.000 --> 14:54.000 We are moving some stuff around. 14:54.000 --> 14:56.000 R0 and R1, these are CPU registers. 14:56.000 --> 15:02.000 And in this case they hold the arguments of the function of the functions. 15:02.000 --> 15:06.000 So R1 is the value t that we see here. 15:06.000 --> 15:11.000 And R0 is the type dictionary that we saw in the previous slides. 15:11.000 --> 15:14.000 So it has actually two arguments, not one. 15:14.000 --> 15:16.000 Because of the type dictionary. 15:16.000 --> 15:20.000 So with these two instructions we are moving them to the stack. 15:21.000 --> 15:23.000 With the next instructions we move some more stuff around. 15:23.000 --> 15:28.000 And actually what happens here is now in R0 we have the value t. 15:28.000 --> 15:32.000 But in R1 we have the string method of our type. 15:32.000 --> 15:35.000 So this was inside the type dictionary. 15:35.000 --> 15:38.000 But with these instructions here. 15:38.000 --> 15:44.000 We took it out of the type dictionary and put it into the CPU register. 15:44.000 --> 15:46.000 R1. 15:46.000 --> 15:49.000 This is the string method of A or B. 15:49.000 --> 15:52.000 We cannot say here because this is just implementation. 15:52.000 --> 15:58.000 So whichever type we use it with this will be the string method. 15:58.000 --> 16:01.000 And then we actually call this method. 16:01.000 --> 16:04.000 The string which is this code here. 16:04.000 --> 16:08.000 So we see here the type dictionary in practice. 16:08.000 --> 16:11.000 So here some more stuff continue to happen. 16:11.000 --> 16:14.000 We see here the code runtime.com to string function. 16:14.000 --> 16:20.000 Which is a function that converges the string value to something that's represented by R1 time. 16:20.000 --> 16:25.000 And then we see the code to print the R1 which is this thing here. 16:25.000 --> 16:29.000 And then we just return the value but I have omitted that. 16:29.000 --> 16:32.000 The power instructions of how I got here. 16:32.000 --> 16:35.000 You can find this githical repository. 16:35.000 --> 16:37.000 You can also find the slides there. 16:37.000 --> 16:42.000 So you can reproduce this example and see if we are self what's going on. 16:42.000 --> 16:48.000 So yeah this is the proposal that got accepted. 16:48.000 --> 16:51.000 This is how genetics are implemented in goal. 16:51.000 --> 16:55.000 And you see here the benefits are kind of the same as the drawbacks. 16:55.000 --> 17:00.000 We have little performance penalty in compile time because we are compiling more shapes. 17:00.000 --> 17:06.000 But they are limited by the number of types that we can produce with different memory representations. 17:06.000 --> 17:11.000 And we still have some performance penalty around time because we are still using these dictionaries. 17:11.000 --> 17:15.000 But we can say they are also limited by the number of types. 17:15.000 --> 17:19.000 I gave this asterisk here that says little to high with an asterisk. 17:19.000 --> 17:23.000 So I want to elaborate on what this means and what this. 17:23.000 --> 17:26.000 What can high mean. 17:26.000 --> 17:30.000 So there is this block post by the folks from one scale. 17:30.000 --> 17:33.000 One scale is a company that does manage the SPL offerings. 17:33.000 --> 17:38.000 So there are a lot of code which is very run some very low levels. 17:38.000 --> 17:40.000 The performance is very important for them. 17:40.000 --> 17:43.000 And shortly after genetics were introduced in 2022. 17:43.000 --> 17:47.000 They wrote this block post that says genetic can make your goal code slower. 17:47.000 --> 17:49.000 I recommend you read the whole bit. 17:49.000 --> 17:51.000 It's a very interesting one. 17:51.000 --> 17:54.000 They do a lot of this assembly similar to what I did. 17:54.000 --> 17:57.000 With much more examples, benchmarks and so on. 17:57.000 --> 17:59.000 So you can see for yourself. 18:00.000 --> 18:11.000 But the TODR is that genetics can introduce a performance hit in the baseline of like two to three microseconds for a function that usually runs in five microseconds. 18:11.000 --> 18:17.000 So this is like a 50% performance hit if you are using genetics. 18:17.000 --> 18:22.000 What they also say in this article is that interfaces can produce a similar performance hit. 18:22.000 --> 18:28.000 Because actually interfaces work in a similar way with the type dictionaries where you start a type information. 18:28.000 --> 18:34.000 So using them can have similar performance hit which is smaller. 18:34.000 --> 18:39.000 So like one to two microseconds for a five microsecond baseline. 18:39.000 --> 18:41.000 So yeah. 18:41.000 --> 18:48.000 And the worst case scenario actually is if you use a genetic function and you give it and you pass interface to genetic function. 18:48.000 --> 18:51.000 Because in this case the performance hits accumulate. 18:52.000 --> 18:55.000 So you can get like. 18:55.000 --> 19:02.000 This thing is accumulates or you can get three to five microseconds per performance penalty for five microseconds function. 19:02.000 --> 19:06.000 So yeah don't if you have if you have a genetic function don't give it interface. 19:06.000 --> 19:12.000 It just give it a specific types. 19:12.000 --> 19:20.000 And yeah if this really matters to you just don't use genetics because the other parts of the goal hasn't gotten any slower because of genetics. 19:20.000 --> 19:25.000 It's just genetics because of the way that they are implemented. 19:25.000 --> 19:29.000 Also I've really never heard someone complain about interfaces being slow. 19:29.000 --> 19:36.000 So I guess for most of us this doesn't really matter because we don't write so performance critical code. 19:36.000 --> 19:41.000 But if you do here this in mind. 19:41.000 --> 19:47.000 So to summary to summarize we have long awaited genetics to be implemented in the language. 19:47.000 --> 19:51.000 The goal team really took their time with it because I guess they just want to make it right. 19:51.000 --> 19:59.000 And even though they are sure for some performance implications I guess for most of us they wouldn't pick a huge impact. 19:59.000 --> 20:02.000 And if they do just I guess don't use them. 20:02.000 --> 20:06.000 And nothing in the specs prevents these from being optimized further. 20:06.000 --> 20:15.000 So in future releases and if people complain more I guess we can we can get some performance fixes. 20:15.000 --> 20:17.000 And let's finish with this table. 20:17.000 --> 20:21.000 We already saw this like the three categories of languages according to the genetic dilemma. 20:21.000 --> 20:24.000 So let's see where the goal stands here. 20:24.000 --> 20:28.000 Do we have the do we have fast programmers now to write genetic code? 20:28.000 --> 20:30.000 Yes. 20:30.000 --> 20:32.000 Do we have fast compilers still? 20:32.000 --> 20:35.000 Yes mostly. 20:35.000 --> 20:39.000 And do we have fast run time? 20:39.000 --> 20:41.000 Yes with some little cave eggs. 20:41.000 --> 20:46.000 So comparing to the other three I would say the goal team did pretty well on genetics. 20:46.000 --> 20:51.000 And I think we are in a good state. 20:51.000 --> 20:52.000 That will be all. 20:52.000 --> 20:55.000 You can see the slide. 20:55.000 --> 20:57.000 Here. 20:57.000 --> 21:00.000 Here. 21:00.000 --> 21:02.000 This is the awesome question. 21:02.000 --> 21:07.000 Do we have any questions which are very important. 21:07.000 --> 21:14.000 If you are leaving do so in your most other most silence. 21:14.000 --> 21:18.000 No questions. 21:18.000 --> 21:20.000 I have a question over there. 21:20.000 --> 21:22.000 I'm going quickly to give you the microphone. 21:22.000 --> 21:25.000 Please keep your hand up. 21:38.000 --> 21:41.000 I was wondering. 21:41.000 --> 21:50.000 I was wondering whether it was possible to use a compiler flag to decide implementation. 21:50.000 --> 21:53.000 For release, you may want to run time. 21:53.000 --> 21:56.000 So in that case, you may want to stand still. 21:56.000 --> 21:59.000 I don't hear anything. 21:59.000 --> 22:06.000 I was wondering whether it was possible to use a compilation flag to determine whether you want 22:06.000 --> 22:10.000 to do it like fast run time. 22:10.000 --> 22:17.000 I did hear something about compilation. 22:17.000 --> 22:18.000 Sorry. 22:18.000 --> 22:20.000 Let me come close to you. 22:20.000 --> 22:27.000 He was wondering if it was possible to add a compilation flag to reduce. 22:27.000 --> 22:37.000 If you could add a compilation flag to disable generics. 22:37.000 --> 22:42.000 I don't think so. 22:42.000 --> 22:52.000 If you want to disable generics, just don't write a code. 22:53.000 --> 22:56.000 It's very hard to hear this code everybody leaving. 22:56.000 --> 22:59.000 If you have more questions, you will be available in the hallway. 22:59.000 --> 23:00.000 You will be available later. 23:00.000 --> 23:01.000 Just say hi. 23:01.000 --> 23:03.000 Give him a free drink or something. 23:03.000 --> 23:06.000 I will have a message for your answers and questions. 23:06.000 --> 23:07.000 Thank you very much. 23:07.000 --> 23:08.000 Run over class.