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:46.000 --> 02:49.000
so they had a big C++ code base,

02:49.000 --> 02:51.000
and one thing which is plus plus,

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:58.000
So, you can do a lot of stuff and the complexity can get quite high.

02:58.000 --> 03:00.000
So, for those that are harder to unboard new people,

03:00.000 --> 03:03.000
especially in more junior ones to their complex code base,

03:03.000 --> 03:05.000
that's why they wanted to have a new language,

03:05.000 --> 03:06.000
which is more simple.

03:06.000 --> 03:09.000
So, what it is years to unboard new people.

03:09.000 --> 03:13.000
Also, C++ is notorious for its slow compilation times,

03:13.000 --> 03:16.760
So they wanted a new language that mitigates that as well.

03:16.760 --> 03:19.120
But they very much liked how fast C++ runs.

03:19.120 --> 03:23.240
So they wanted to keep this in a new language that they created.

03:23.240 --> 03:25.680
And that's how it came to be.

03:25.680 --> 03:29.880
However, it turns out that genetics kind of complicate each one

03:29.880 --> 03:31.360
of these three conditions.

03:31.360 --> 03:34.000
So back then in 2009, it kind of makes sense

03:34.000 --> 03:36.880
that to not have genetics in the language.

03:36.880 --> 03:39.880
However, it took them less than 24 hours

03:39.880 --> 03:41.280
for people with the internet to start

03:41.280 --> 03:44.400
on planning about the lack of genetics.

03:44.400 --> 03:48.120
Yeah, this is a Google group, a discussion about the language.

03:48.120 --> 03:49.760
And you see, this is November 11.

03:49.760 --> 03:52.040
So one day after the language was released,

03:52.040 --> 03:55.000
someone complained that the language doesn't have genetics.

03:55.000 --> 03:57.680
And this kind of set the tone of how the next few years

03:57.680 --> 04:00.320
are going to the combined people will continue

04:00.320 --> 04:02.160
complaining about the lack of genetics.

04:02.160 --> 04:04.680
It's always going to be one of the most requested features

04:04.680 --> 04:06.400
to be able to the language.

04:06.400 --> 04:08.720
So what did the goal team do about that?

04:08.720 --> 04:10.880
It turns out they did quite a lot.

04:10.880 --> 04:13.560
So one year later, we got the first proposal for genetics.

04:13.560 --> 04:15.360
It was called type functions.

04:15.360 --> 04:16.640
It was rejected.

04:16.640 --> 04:22.080
Obviously, then we had another one, 2011 called generalized types.

04:22.080 --> 04:24.960
Then we had two more into an 13, called type parameters

04:24.960 --> 04:27.040
and generalized types V2.

04:27.040 --> 04:29.760
As you know, all of them were rejected.

04:29.760 --> 04:32.480
All four of those proposals came from within the goal team.

04:32.480 --> 04:35.240
And the majority of work was done by one guy.

04:35.240 --> 04:37.760
He was called Ian Lansteuer.

04:37.760 --> 04:40.840
So yeah, this effort came from the goal team itself.

04:41.800 --> 04:44.000
Then we had some radio silence on the topic.

04:44.000 --> 04:46.880
But in 2018, in 2019, we got two more proposals

04:46.880 --> 04:49.640
called contracts and contracts V2.

04:49.640 --> 04:55.600
Essentially, this, we got one more in 2021 type parameters.

04:55.600 --> 04:58.440
And this is actually the proposal that the goal accepted.

04:58.440 --> 05:00.360
And these three proposals, they were still written

05:00.360 --> 05:03.360
by the same guy from before.

05:03.360 --> 05:05.640
So yeah.

05:05.640 --> 05:09.600
Finally, he got his way in, we got genetics.

05:09.600 --> 05:12.800
We did this final proposal.

05:12.800 --> 05:14.080
So what took them so long?

05:14.080 --> 05:15.920
Obviously, the goal team wants to do that.

05:15.920 --> 05:17.960
All these proposals came from within the goal team.

05:17.960 --> 05:19.960
The community also wanted to hear that.

05:19.960 --> 05:22.240
So what took them so long?

05:22.240 --> 05:24.160
I think, last of this question, we need to get back

05:24.160 --> 05:26.560
to this book post by Roscox.

05:26.560 --> 05:28.240
It's from December 2009.

05:28.240 --> 05:30.840
So this is the first month of the language.

05:30.840 --> 05:33.560
And it's called the genetic dilemma.

05:33.560 --> 05:36.040
What it says in this article, it's basically

05:36.040 --> 05:38.000
he came to the conclusion that the genetic dilemma

05:38.000 --> 05:41.560
is do we want slow programmers, slow compilers,

05:41.560 --> 05:43.800
or slow execution times?

05:43.800 --> 05:46.840
So what Roscox did was he looked at all these other languages

05:46.840 --> 05:48.720
that already existed back then.

05:48.720 --> 05:52.360
And he looked at how they implemented genetics.

05:52.360 --> 05:55.080
And he realized that if you want genetics or don't want

05:55.080 --> 06:00.320
genetics, you'll need to choose one of three trade-offs.

06:00.320 --> 06:03.560
He basically came up with three categories of languages.

06:03.560 --> 06:05.240
The first one is languages like C.

06:05.240 --> 06:09.400
But don't get genetics, so you don't have the productivity boost

06:09.400 --> 06:11.160
that feature like genetics give you.

06:11.160 --> 06:14.040
But you do have fast compilers and fast run times.

06:14.040 --> 06:16.920
Then you have C++, where you do have genetics.

06:16.920 --> 06:18.800
And you do have the fast run time.

06:18.800 --> 06:20.920
But you have you get the slow compilation time

06:20.920 --> 06:23.520
because of the way genetics are implemented.

06:23.520 --> 06:28.120
And then you have Java, where again, you have fast programmers.

06:28.120 --> 06:29.280
You have fast compilers.

06:29.280 --> 06:31.200
But because of the way genetics are implemented,

06:31.200 --> 06:34.200
which is completely different than C++,

06:34.200 --> 06:36.800
you get the performance heating in runtime.

06:36.800 --> 06:39.400
And having in mind that, already,

06:39.400 --> 06:42.200
did have limited support for genetics for the building types,

06:42.200 --> 06:45.400
like maps, slices, channels.

06:45.400 --> 06:48.960
I guess they just didn't want to take any one of these three trade-offs

06:48.960 --> 06:52.840
and just decided to leave the things as they are.

06:52.840 --> 06:56.200
But as we show, we already have an accepted proposal.

06:56.200 --> 06:58.560
And now let's talk about the implementation.

06:58.560 --> 07:01.160
Let's see what this proposal tells us about how genetics

07:01.160 --> 07:02.120
are going to be implementing.

07:02.120 --> 07:04.120
Go.

07:04.120 --> 07:06.280
Well, it didn't tell us anything.

07:06.280 --> 07:08.000
Oh, the final proposal went also

07:08.000 --> 07:09.080
for all the previous one.

07:09.080 --> 07:11.960
In their implementation paragraph, they say,

07:11.960 --> 07:13.920
we are aware of the genetics dilemma.

07:13.920 --> 07:16.200
We don't want to take a decision on this.

07:16.200 --> 07:18.480
The proposal is flexible enough so that you can implement it

07:18.480 --> 07:19.720
however you like.

07:19.720 --> 07:22.320
So basically, it doesn't give us any any guides on how

07:22.320 --> 07:24.360
it's going to be implemented.

07:24.360 --> 07:25.360
So what do we do?

07:25.360 --> 07:29.960
We need to write more proposals for the actual implementation.

07:29.960 --> 07:33.240
In reality, there were three proposals written for the implementation.

07:33.240 --> 07:36.160
The final one was accepted, but for us

07:36.160 --> 07:39.960
to better understand how we came to how we came there,

07:39.960 --> 07:45.320
we need to look at all three other proposals.

07:45.320 --> 07:46.920
The first one is called Stencelink.

07:46.920 --> 07:50.240
And this is basically the simplest way of doing things.

07:50.240 --> 07:52.920
And Stencelink means that when we have a genetic function

07:52.920 --> 07:55.440
and we use it with some types, we're

07:55.440 --> 07:57.960
going to compile one function for all the types

07:57.960 --> 08:00.240
that we use our genetic function with.

08:00.240 --> 08:02.440
Let's see an example.

08:02.440 --> 08:04.280
On the left, we have a genetic code,

08:04.280 --> 08:07.640
pretty simple function that just takes two values

08:07.640 --> 08:10.280
and turns the sum of them.

08:10.280 --> 08:12.920
And we are calling it with first with integers

08:12.920 --> 08:15.000
and then with floating point numbers.

08:15.000 --> 08:17.240
What we have done during compilation is that the compiler

08:17.240 --> 08:20.560
will actually produce two functions.

08:20.560 --> 08:23.480
The first one we work with just integers,

08:23.480 --> 08:26.240
the second one we work with just floats.

08:26.240 --> 08:30.320
And on the coincide, we're going to replace the genetic function

08:30.320 --> 08:32.320
with the specific implementation of this function

08:32.320 --> 08:33.760
for this type.

08:33.760 --> 08:35.560
Of course, this is just pure code.

08:35.560 --> 08:38.160
The GoCompower doesn't produce any GoCode,

08:38.160 --> 08:39.680
it produces machine code.

08:39.680 --> 08:42.200
But it's just an illustration of how this is going

08:42.200 --> 08:43.720
to look like according to the proposal.

08:46.280 --> 08:47.640
So yeah, this is done.

08:47.640 --> 08:52.240
This is the georepter notation and the floating implementation.

08:52.240 --> 08:54.120
The big benefits here are that you basically

08:54.120 --> 08:56.320
don't have any performance during any performance

08:56.320 --> 08:57.440
penalty during current time.

08:57.440 --> 08:58.760
Because in your own time, you don't

08:58.760 --> 09:01.360
have genetic functions, we have regore functions.

09:01.360 --> 09:04.360
However, the performance hits come during compilation.

09:04.360 --> 09:06.120
Now the compiler has to do a lot more work

09:06.120 --> 09:09.200
to compile this function multiple times for each of the types

09:09.200 --> 09:10.880
that we work with.

09:10.880 --> 09:13.000
And this also contributes to the bigger binary size,

09:13.000 --> 09:16.080
because now we have more stuff in our compiled binary.

09:16.080 --> 09:21.000
So because of these reasons, this proposal was rejected.

09:21.000 --> 09:22.960
The second proposal is called dictionaries,

09:22.960 --> 09:26.600
and this is more or less the way Java does generics.

09:26.600 --> 09:30.440
This says we're going to compile a single function

09:30.440 --> 09:32.040
for the genetic function.

09:32.040 --> 09:33.560
And we're going to use dictionaries

09:33.560 --> 09:36.720
to keep all the type information for the specific types

09:36.720 --> 09:39.720
that we use our function with.

09:39.720 --> 09:41.800
Let's see how this looks like.

09:41.800 --> 09:45.840
Again, we have the same simple function.

09:45.840 --> 09:48.840
And after compilation, this looks like this.

09:48.840 --> 09:50.240
Now you see on the left, we have just

09:50.240 --> 09:53.400
a single implementation of our same diff function.

09:53.400 --> 09:56.000
And we see here are two arguments A and B.

09:56.000 --> 09:58.560
But now they are just pointer.

09:58.560 --> 09:59.840
Point pointers.

09:59.840 --> 10:02.440
And the return value is also pointer.

10:02.440 --> 10:04.320
But we also see we have one more argument

10:04.320 --> 10:05.760
that's being connected to our function.

10:05.760 --> 10:09.120
And this is this thing here, the dictionary.

10:09.120 --> 10:11.680
And this here contains all the type information

10:11.680 --> 10:14.120
for the types that we are using this function with.

10:14.120 --> 10:16.320
You see on the top, we have the type.

10:16.320 --> 10:19.440
And it also, like all the functions that are present

10:19.440 --> 10:22.800
on these types, we have them in the dictionary as well.

10:22.800 --> 10:25.280
In this case, the data function

10:25.280 --> 10:28.000
has substitutes the plus operator.

10:28.000 --> 10:30.560
What happens when we call such function,

10:30.560 --> 10:35.200
you see here, we are calling it with two integers.

10:35.200 --> 10:39.800
The compiler now needs to box these values into pointers.

10:39.800 --> 10:42.800
And it needs to come up with this dictionary

10:42.800 --> 10:44.520
that provides implementation.

10:44.520 --> 10:46.080
And you see in the implementation, we actually need

10:46.080 --> 10:48.600
to unbox these values to get there,

10:48.600 --> 10:50.160
to get their actual integer values.

10:50.160 --> 10:51.360
We need to sum them.

10:51.360 --> 10:53.840
And then we need to box this again into a pointer

10:53.840 --> 10:55.640
to enter and return it.

10:55.640 --> 10:59.240
And here, we need to unbox that return value, again,

10:59.240 --> 11:02.640
to get the actual value.

11:02.640 --> 11:04.240
This doesn't have a big performance

11:04.240 --> 11:06.440
penalty in compilation time.

11:06.440 --> 11:08.320
Yes, the compiler does more work, work,

11:08.320 --> 11:10.080
but we can say it's negligible.

11:10.080 --> 11:13.480
However, the big penalty here comes during runtime.

11:13.480 --> 11:16.280
Because all these referencing can be referencing,

11:16.280 --> 11:20.880
it just adds some overhead, and it makes our code run slower.

11:20.880 --> 11:23.360
Also, it kind of prevents compiler inlining,

11:23.360 --> 11:26.480
because now a lot of the information is not present

11:26.480 --> 11:28.880
in compile time is present only through runtime.

11:28.880 --> 11:32.200
So this prevents the compiler from inlining our stuff.

11:32.200 --> 11:34.160
And I'm not an expert in compilers,

11:34.160 --> 11:37.600
but I know that this is generally a good thing inlining.

11:37.600 --> 11:39.640
And when we're using this approach,

11:39.640 --> 11:41.680
we are preventing the compiler from doing this nice

11:41.680 --> 11:43.720
optimization for us.

11:43.720 --> 11:45.880
So we can say we get a big performance

11:45.880 --> 11:47.760
hitting in runtime.

11:47.760 --> 11:51.960
And this is why this proposal will reject it.

11:51.960 --> 11:55.920
So we can't return proposal, which is called gc shape stenciling.

11:55.920 --> 11:58.120
This is the proposal that actually got accepted.

11:58.120 --> 11:59.720
And this is more or less the middle ground

11:59.720 --> 12:02.040
between the first two proposals.

12:02.040 --> 12:03.920
So they said stenciling is bad.

12:03.920 --> 12:05.200
Dictionary is our bad.

12:05.200 --> 12:06.200
Let's do both.

12:11.200 --> 12:13.560
Yeah, so as I said, this is the middle ground.

12:13.560 --> 12:14.960
So it does a little bit of stenciling

12:14.960 --> 12:16.480
and a little bit of dictionaries.

12:16.480 --> 12:18.280
And actually what it does is,

12:18.280 --> 12:23.400
it does produce multiple versions of our functions.

12:23.400 --> 12:25.880
But the only for types that have different representation

12:25.880 --> 12:28.440
in memory, this is what gc shape stands for,

12:28.440 --> 12:30.280
garbage collector shape.

12:30.280 --> 12:33.520
So types that have the same memory representation,

12:33.520 --> 12:37.040
we get the same implementation of the generic function.

12:37.040 --> 12:40.440
And the type information we present in these dictionaries.

12:40.440 --> 12:43.240
This is the proposal that got accepted.

12:43.240 --> 12:45.720
So how this looks like?

12:45.720 --> 12:48.160
I have here still a simple example of a different

12:48.160 --> 12:49.880
in the previous one.

12:49.880 --> 12:52.320
I have a generic function called pint and return.

12:52.320 --> 12:55.160
It accepts type t, which needs to satisfy the string

12:55.160 --> 12:56.560
or interface.

12:56.560 --> 12:59.440
It gets the value of the string.

12:59.440 --> 13:02.720
It brings it and it just returns the value t.

13:02.720 --> 13:05.840
Pretty stupid function, but it works for an example.

13:05.840 --> 13:08.360
And I'm calling this function four times, four times,

13:08.360 --> 13:09.880
with four different types.

13:09.880 --> 13:12.960
First time with an integer, then with a string,

13:12.960 --> 13:14.800
they are wrapped into their own custom type

13:14.800 --> 13:17.920
so that we can provide the string implementation.

13:17.920 --> 13:21.760
And then with two structs, A and B, which

13:21.760 --> 13:24.120
I am passing as pointers.

13:24.120 --> 13:27.080
So let's see how this looks like after compilation.

13:27.080 --> 13:28.840
But now we don't need to look at two to code,

13:28.840 --> 13:31.320
because this is the actual implementation of generics.

13:31.320 --> 13:33.200
So we can do something better.

13:33.200 --> 13:36.720
While I did, I compiled this code.

13:36.720 --> 13:39.240
I gave it some compiler flags to prevent

13:39.240 --> 13:41.240
optimization and inlining.

13:41.240 --> 13:43.640
And then I used a go-to object dump command

13:43.640 --> 13:47.360
to do the sample executed by what they got from the go-butth.

13:47.360 --> 13:51.080
And we can actually look at some of this sample code.

13:51.080 --> 13:53.360
This is how it looks like.

13:53.360 --> 13:55.200
On the right is that this is the sample code.

13:55.200 --> 13:57.760
And we see the shapes of the compiler produced.

13:57.760 --> 14:02.280
So we see how our function was compiled three times.

14:02.280 --> 14:05.240
But why three times, if we call it four different types,

14:05.240 --> 14:07.600
well, because A and B, they are just pointers.

14:07.600 --> 14:09.400
So they hear the same memory representation.

14:09.400 --> 14:11.840
They're just a U in date.

14:11.840 --> 14:20.240
So the compiler compiled only one shape for these two types.

14:20.240 --> 14:24.880
Let's dive into the implementation of this function.

14:24.880 --> 14:26.480
Yeah, this is for the integer.

14:26.480 --> 14:29.960
You see here, go shape int.

14:29.960 --> 14:33.240
This indicates that this is for the integer.

14:33.240 --> 14:38.160
Then you have the string here for the string value.

14:38.160 --> 14:41.240
And then you have the U in date for the pointers.

14:41.240 --> 14:46.480
So let's dive into that function.

14:46.480 --> 14:50.640
So let's see what happens, what happens inside.

14:50.640 --> 14:54.200
We see here in the beginning, we are moving some stuff around.

14:54.200 --> 14:56.680
R01, these are CPU registers.

14:56.680 --> 15:02.560
And in this case, they hold the arguments of the function.

15:02.560 --> 15:07.000
So R1 is the value t that we see here.

15:07.000 --> 15:11.440
And R0 is the type dictionary that we saw in the previous slides.

15:11.440 --> 15:16.240
So it has actually two arguments, not one, because of the type dictionary.

15:16.240 --> 15:20.840
So with these two instructions, we are moving them to the stack.

15:20.840 --> 15:23.440
With the next instructions, we move some more stuff around.

15:23.440 --> 15:28.160
And actually what happens here is now in R0, we have the value t.

15:28.160 --> 15:32.240
But in R1, we have the string method of our type.

15:32.240 --> 15:35.400
So this was inside the type dictionary.

15:35.520 --> 15:40.120
But with these instructions here, we took it out of the type dictionary

15:40.120 --> 15:46.680
and put it into the CPU register R1.

15:46.680 --> 15:48.840
This is the string method of A or B.

15:48.840 --> 15:52.280
We cannot save here, because this is just implementation.

15:52.280 --> 15:58.680
So whichever type we use it with, this will be the string method.

15:58.680 --> 16:05.200
And then we actually call this method, the string, which is this code here.

16:05.200 --> 16:08.760
So we see here the type dictionary in practice.

16:08.760 --> 16:10.960
So here some more stuff continue to happen.

16:10.960 --> 16:14.400
We see here the code R1 time.com to the string function,

16:14.400 --> 16:17.840
which is a function that converges the string value

16:17.840 --> 16:21.160
to something that's represented by R1 time.

16:21.160 --> 16:25.760
And then we see the code to print a one, which is this thing here.

16:25.760 --> 16:30.160
And then we just return the value, but I have omitted that.

16:30.160 --> 16:32.840
The following instructions of how I got here,

16:32.840 --> 16:36.040
you can find this githical repository.

16:36.040 --> 16:37.640
You can also find the slides there.

16:37.640 --> 16:39.880
So yeah, you can reproduce this example

16:39.880 --> 16:42.080
since you see for yourself what's going on.

16:45.080 --> 16:48.760
So yeah, this is the proposal that got accepted.

16:48.760 --> 16:51.360
This is how genetics are implemented in goal.

16:51.360 --> 16:55.240
And you see here the benefits are kind of the same as drawbacks.

16:55.240 --> 16:58.320
We have little, little performance penalty in compile time,

16:58.320 --> 17:01.120
because we are compelling more shapes,

17:01.120 --> 17:02.920
but they are limited by the number of types

17:02.920 --> 17:06.760
that we can produce with different memory representations.

17:06.760 --> 17:08.560
And we still have simple performance penalty

17:08.560 --> 17:11.120
around time, because we're still using these dictionaries.

17:11.120 --> 17:15.680
But we can say they are also limited by the number of types.

17:15.680 --> 17:17.840
I can just ask this here that says little to high,

17:17.840 --> 17:18.720
put an asterix.

17:18.720 --> 17:21.600
So I want to elaborate on what this means,

17:21.600 --> 17:26.320
and what this, what can high mean.

17:26.320 --> 17:30.000
So there is this rock post by the folks from one at scale,

17:30.000 --> 17:33.680
one at scale with a company that does manage the SPR offerings.

17:33.680 --> 17:36.560
So there are a lot of code, which is very,

17:36.560 --> 17:39.840
runs on very low levels, so performance is very important for them.

17:39.840 --> 17:43.440
And shortly after genetics were introduced in 2022,

17:43.440 --> 17:46.160
they wrote this block post that says genetic can make your goal

17:46.160 --> 17:47.600
code slower.

17:47.600 --> 17:49.240
I recommend you read the whole of it.

17:49.240 --> 17:50.400
It's a very interesting one.

17:50.400 --> 17:54.600
They do a lot of, this assembly similar to what I did.

17:54.600 --> 17:56.920
With much more examples, benchmark and so on.

17:56.920 --> 18:00.040
So you can see for yourself.

18:00.040 --> 18:03.560
But the TODR is that genetics can introduce

18:03.560 --> 18:08.680
a performance hit in a baseline of two to three microseconds

18:08.680 --> 18:11.480
for a function that usually runs in five microseconds.

18:11.480 --> 18:15.000
So this is like a 30% performance hit

18:15.000 --> 18:17.520
if you're using genetics.

18:17.520 --> 18:20.120
What they also say in this article is that interfaces

18:20.120 --> 18:22.200
can produce a similar performance hit,

18:22.200 --> 18:25.560
because it actually interfaces work in a similar way

18:25.560 --> 18:28.600
with the type dictionaries where you start a type information.

18:28.600 --> 18:32.920
So using them can have similar performance hit,

18:32.920 --> 18:36.680
which is smaller, so like one to two microseconds

18:36.680 --> 18:39.680
for a five microsecond baseline.

18:39.680 --> 18:40.920
So yeah.

18:40.920 --> 18:43.160
And the worst case scenario actually

18:43.160 --> 18:45.760
is if you use a genetic function

18:45.760 --> 18:48.800
and you give it a new pass interface to genetic function.

18:48.800 --> 18:51.920
Because in this case, the performance hits accumulate.

18:51.920 --> 18:56.040
So you can get, like, these things accumulate,

18:56.040 --> 19:00.040
so you can get 3 to 5 microseconds performance penalty

19:00.040 --> 19:02.640
for a five microsecond function.

19:02.640 --> 19:05.360
So yeah, if you have a genetic function,

19:05.360 --> 19:06.400
don't give it interface.

19:06.400 --> 19:09.640
You just give it a specific type.

19:12.480 --> 19:14.480
And yeah, if this really matters to you,

19:14.480 --> 19:18.760
just don't use genetics, because the other parts of a goal

19:18.760 --> 19:21.160
hasn't gotten any slower because with genetics,

19:21.160 --> 19:24.960
is just genetics because of the way that they are implemented.

19:24.960 --> 19:27.040
Also, I've really never heard someone complain

19:27.040 --> 19:28.760
about interfaces being slow.

19:28.760 --> 19:31.880
So I guess for most of us, this doesn't really matter,

19:31.880 --> 19:36.160
because we don't write so performance critical code.

19:36.160 --> 19:37.960
But if you do, here this in mind.

19:40.680 --> 19:44.800
So to summary, to summarize, we have long-awaited genetics

19:44.800 --> 19:47.520
to be implemented in the language.

19:47.520 --> 19:48.960
The goal team really took their time with it,

19:48.960 --> 19:51.800
because I guess they just want to make it right.

19:51.800 --> 19:54.200
And even though they are serve for some performance

19:54.200 --> 19:58.920
implications, I guess for most of us, they wouldn't pick a huge impact.

19:58.920 --> 20:01.880
And if they do, just, I guess, don't use them.

20:01.880 --> 20:05.680
And nothing in the specs prevents these from being optimized

20:05.680 --> 20:06.160
further.

20:06.160 --> 20:09.080
So in future releases, and if people complain more,

20:09.080 --> 20:13.120
I guess we can get some performance fixes.

20:15.640 --> 20:17.120
And let's finish with this table.

20:17.120 --> 20:20.360
We already saw this, like the three categories of languages

20:20.360 --> 20:21.680
according to the genetic dilemma.

20:21.680 --> 20:24.160
So let's see where both ends here.

20:24.160 --> 20:26.840
Do we have the, do we have fast programmers now

20:26.840 --> 20:28.880
so we can write genetic code?

20:28.880 --> 20:30.360
Yes.

20:30.360 --> 20:32.760
Do we have fast compilers still?

20:32.760 --> 20:33.600
Yes, mostly.

20:36.120 --> 20:39.640
And do we have fast runtime?

20:39.640 --> 20:41.480
Yes, we have some little cave eggs.

20:41.480 --> 20:44.400
So comparing to the other three, I would say the goal team

20:44.400 --> 20:46.040
did pretty well on genetics.

20:46.040 --> 20:48.360
And I think we are in a good state.

20:50.920 --> 20:51.720
That's all we owe.

20:51.720 --> 20:53.720
You can see the slide here.

20:53.720 --> 20:54.720
Here.

20:56.080 --> 20:56.920
Here.

20:56.920 --> 20:57.920
Here.

21:00.560 --> 21:01.680
This is the awesome question.

21:01.680 --> 21:03.080
Yeah, that's it.

21:03.080 --> 21:07.200
Do we have any questions which are very important?

21:07.200 --> 21:10.400
If you are leaving, do so in your most other most silenced.

21:10.400 --> 21:11.400
Yes.

21:14.400 --> 21:15.400
No questions.

21:19.400 --> 21:20.400
I have a question over there.

21:20.400 --> 21:22.400
I'm going to quickly give you the microphone.

21:22.400 --> 21:23.400
Please keep your hand up.

21:35.400 --> 21:36.400
Hey.

21:37.400 --> 21:39.400
Hey, sorry.

21:39.400 --> 21:40.400
I was wondering.

21:40.400 --> 21:41.400
I was wondering.

21:45.400 --> 21:49.400
I was wondering whether it was possible to use a compiler flag

21:49.400 --> 21:50.400
to decide implementation.

21:50.400 --> 21:51.400
Like for release build.

21:51.400 --> 21:52.400
You may want some runtime.

21:52.400 --> 21:53.400
Right?

21:53.400 --> 21:55.400
So in that case, you may want stenciling approach.

21:55.400 --> 21:56.400
No?

21:56.400 --> 21:58.400
I don't hear anything, no?

22:00.400 --> 22:04.400
I was wondering whether it was possible to use a compilation flag

22:04.400 --> 22:07.400
to determine whether you want fast runtime.

22:07.400 --> 22:10.400
So like stenciling approach and otherwise.

22:10.400 --> 22:12.400
I did hear something about compilation.

22:17.400 --> 22:18.400
Sorry.

22:18.400 --> 22:19.400
Let me come close to you.

22:19.400 --> 22:20.400
Yeah.

22:20.400 --> 22:24.400
He was wondering if it was possible to add a compilation flag

22:24.400 --> 22:25.400
to refuse.

22:25.400 --> 22:28.400
For me, this would correct.

22:28.400 --> 22:32.400
I would use the slowness in the code.

22:32.400 --> 22:35.400
If you could add a compilation flag to disable generics.

22:35.400 --> 22:36.400
To disable generics?

22:36.400 --> 22:37.400
No.

22:37.400 --> 22:38.400
No.

22:38.400 --> 22:39.400
I don't think so.

22:42.400 --> 22:44.400
I mean, if you want to disable generics,

22:44.400 --> 22:46.400
just don't write generic code to just write.

22:52.400 --> 22:53.400
I don't hear anything.

22:53.400 --> 22:56.400
It's very hard to hear this code everybody leaving.

22:56.400 --> 22:59.400
If you have more questions, you will be available in the hallway

22:59.400 --> 23:02.400
later, just say hi, giving me a free drink or something.

23:02.400 --> 23:05.400
And you will happily set your answers and questions.

23:05.400 --> 23:06.400
Thank you very much.

23:06.400 --> 23:07.400
Run over glass.

23:07.400 --> 23:08.400
Thank you.

