CppCon 2019: Miro Knejp “Non-conforming C++: the Secrets the Committee Is Hiding From You”

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

This talk is quite entertaining and I hope that some of the things he has shown will get into the standard C++ eventually (maybe in C++23)

👍︎︎ 22 👤︎︎ u/stilgarpl 📅︎︎ Oct 01 2019 🗫︎ replies

The GCC maintainer at the end remarks that the compiler is unable to perform the switch optimization due to the flow in the optimizer. Is this something that will eventually be remedied or are we encouraged to forever use these extensions instead?

👍︎︎ 14 👤︎︎ u/vlind 📅︎︎ Oct 01 2019 🗫︎ replies

I really want to have the conditions with omitted operands (elvis operator). It would make things look so much better

👍︎︎ 17 👤︎︎ u/Kwdg 📅︎︎ Oct 01 2019 🗫︎ replies

The flexible array is standard C99 thats why it works. There was even a talk about it on NDC a week back.

https://youtu.be/ieERUEhs910

👍︎︎ 5 👤︎︎ u/Unsttopabull 📅︎︎ Oct 01 2019 🗫︎ replies

Standards aren't really all that relevant/useful unless people stick to them. If they aren't routinely adhered to they are just wishful thinking flapping in the breeze...

👍︎︎ 9 👤︎︎ u/istarian 📅︎︎ Oct 01 2019 🗫︎ replies

This talk is the most informative so far for me from all the conference. I know it is a bit edge-C++, but anyway, practical and useful for real life.

👍︎︎ 1 👤︎︎ u/germandiago 📅︎︎ Oct 02 2019 🗫︎ replies
Captions
alright then good afternoon everyone my name is Mira and I'm going to talk to you about right non-conforming C++ or as I would also like to call it the committee exposed because today you will see and hear things that will fundamentally challenge your understanding of the C++ committee and hour from now you will have a very different view important who they are you also all believe that you came out of your own free will but no you have not I have made you come here with a little bit of mind control because I know that you are programmers open-minded enough to be receptacle for the truths I'm going to reveal to you today if you want to know how I did it was that impressive camera rates if yeah but you know now that I told you how easy to manipulate people I have to protect myself because there are lots and lots of patrons of the committee in this building today the whole week and so I have to make sure the data cannot stop this you cannot stop this anymore this will happen whether you want or not because oh you don't think this is a joke right you laughing because this is funny to you well let me tell you after I announced this talk on Twitter about two months ago I have received thinly veiled death threats on Twitter in public by agents of the committee they did audacity they think they are untouchable one of them said and I quote good thing we're a committee and other mafia you'd be swimming with the fishes for the street I have been living in fear ever since because I'm afraid that I couldn't just something worse and another quote from another agent C++ is what the Committee says it is c plus plus plus plus is not C++ I'm honestly not sure this means I think it's code for something and there unfortunately no fish in Denver I'm pretty sure that's wrong but I'm glad they believe it and it didn't stop there about a week ago was invited on CPP cast and only days after the episode went live I have received a message saying also we will have to get rid of CPP cast and its host because of you can't have people spread lies so Rob and Jason I am really really sorry I have to apologize to you at one point in the episode I have accused you of being compromised by the committee and now I know the truth and I am really sorry that I put you in danger okay yeah you better you know leave the country though it's it's international I don't know but maybe after this is over you'll be safe again you'll see okay so now with this out of the way you now understand the gravity of the situation although anti-gravity is in a different talk I'm sorry we start like one of the first treasures of the secret committee box and that is case ranges so I'm pretty sure many of you have seen switches like this where you have many cases that are exiting to the same code and it's tedious and it's error-prone and so a normal person is going to say I'm going to use anything else unfortunately now I've lost the declarative nature of the switch statement is what the GCC developers thought and so it said let's add switch ranges case ranges so you can just use dot or dot between two values and it's going to generate all the cases with those two values inclusive so what it's like you've received forbidden knowledge from the committee today for the first time how does it feel it's exciting isn't it so let's keep going the next one unnamed structured Union foods this one has leaked so much people think it's actually part of the language but it is not what we see here is a union without a type and a struct without the type and both declare members inside the outer structure now the union is fine this truck is not who knows why we can simplify this a little bit and just remove the outer structure because in 2011 the committee finally decided to declassify unrestricted unions and so we can have special member functions what can we do with this I mean if you've Anathem graphics engine development or game development or if you look at any of the tutorial on the internet you will have seen something like this that you can use the floats in this structure either by name or by indexing the array which is kind of useful because you can use dynamic indices to refer to your structure members and many api is required to pass in floats as a pointer to a ray so you don't have to reinterpret cast around and the thing is though if you are respectable C++ company then at some point in your life you're going to hire you know these experts to tell you how to code write in C++ they're going to come to you look at your code and say you can do that that's a different behavior oh no oh no oh no a sudden surge of panic comes over you because they set the humor than the B word in the same sentence and that means you have to write everything from scratch but you have to keep calm and you have to stare at them stare at them real hard and some more and then we follow your confidence you say so what we got millions of Webster awning it works on all machines and then they just walk away now you have saved yourself a lot of money and even for the C++ rebellion but your thinking has a C++ all I've seen so far C can I just overload the subscript operator but you can well it turns out the compiler doesn't like it so much I've tried and the generated code isn't as nice and also I'm pretty sure that this here becomes undefined behavior because you cannot just turn a field float into an array all right coming next conditionals with omitted operands quite a mouthful of the name imagine the scenario you're writing some kind of configuration system and you're reading it configuration file values form a file you represent these using the read function and the default value function they return have unique point of something you don't really care right now and you have this little convenience function that if the value does not exist in the file you're just going to return the default now this this cries like I should use I should be able to use the conditional operator right it's an if return else return it's like the perfect use case unfortunately when you try you realize that you're running into a problem because the left expression if it evaluates to a normal pointer it's gonna call the read again and if read has side effects you probably just trashed your configuration system if for example you develop it one sorry it advances so you have to host this read out of the conditioner which looks ugly but you know it still does the job but let's look again at this expression this operator the way it works you have an expression on the left followed by question mark an expression in the middle colon an expression on the right the problem it has the property that both the expressions on the right have to have in compare not in their compatible types because the expression as a whole must have a type so both the result of course of these expressions has to be implicitly convertible to one type so there's people that CP g CC thought we can do better and they decided to create a version that you can just remove the middle part and it's the equivalent as if you just repeated the left expression put it in the middle except it is only evaluated once now you might be thinking that kind of breaks the type system right because we now have an expression of a bull with something else and it doesn't work but it does because the way this works is the expression on the left is evaluated in its entirety and that's the type of the expression and only after that the conversion to pool happens so this expression here works it doesn't cause any type problems and it does what we wanted to do and it's very concise easy to read then you're gonna leave here and look this up on the Internet you are going to realize that people call this the Elvis operator in fact other languages openly admit that they have the Aldous operator but not in C++ and not in C they don't they're hiding this from us I don't know why and also by even Elvis operate I mean I mean let's look at it okay for me it's obvious when I look at this I clearly see Alice yeah when you maybe tilt your head a bit okay at some point you're just gonna see the face of all this and I I don't know if you can see it I definitely see it and it just can't get it out of my Dan anyway have you thought about what this means why does the C++ and C committees why do they so desperately try to keep this away from us because they know that the king is alive the conspiracy is so deep you you wouldn't understand okay another very quick and short one so let's go further and have a look at designated initializers so here in the disassemble be a page structure and ordinarily you would be able to use aggregate initialization to construct in such a structure but just have big curly braces and putting the values in the right order this extension lets you use the names of the fields in the constructor so that you know what you're actually initializing inside the structure and this is very useful because now you don't don't have the confusion between the two bullets you see which one gets which value and we can use that to imitate something other languages have called named parameters for example if we for the function like this that takes one such as structures its parameter and then we can construct it in place and this looks a lot like if we actually have two named parameters in the language doesn't it and it's much easier to read than this because if you don't have the declaration you don't know what true what false what it's not obvious fortunately this has been declassified after decades we finally getting into C++ 20 so I won't go into more detail here because the public information is now a variable about this however the committee in its infinite malice decided no you're not getting the full thing because there's more so this is an area that I see a lot you have some kind of enumeration in this case it's just names for colors and then you have some associated arrays right and the idea is that you use the enumeration as the key to get some value that is associated with this enumeration like the string or the color value on the screen though if you if you let someone like me into your code I'm just gonna say I can handle this no I can't have an unsorted list of names I just can't this is too much but now I've broken everything and I may not even notice because these arrays may be in completely different files or systems of my project so yeah green yeah no no you're not getting green are you getting but black here the code for white no it's it's the code for yellow sorry if you don't have good tests it's gonna take a while till you notice I guess so of course the obvious thing to do is well let's put those damn values in there I don't actually care about them I don't care that red is you I don't care that black is three but I need them because now if someone like me comes along it works however it's tedious because neither want to add a new value I have to actually find the biggest one in the list and incremental I hate it and the people at GCC agree with me so they decided yeah you're just gonna let you specify the index of the value in square brackets and what happens now is no matter the order of the values of enumeration the compiler will put the array values in the correct order that solves all the problems I had I had no long I have to care about the values of my enums and I can sort them I'm happy the syntax for this is very simple really you just use these square brackets with the index and assign it a value the values you do not mention are set to zero if you have a value that follows one of these with an index it just gets the next index so 24 is so sign to index 3 and we can even omit the size of the array because it can be deduced from the biggest index that we specified and so naturally this array here has size 7 because 11 here gets the index 6 and the order of those indices of course does met otherwise our previous example would broke but wait there's more I think we all know how to create an array of zeros right that's trivial but what if I need an array of ones from baby for a Cindy mask or something like that I just have to spell it out and I hope I don't scrub because one is missing my last value zero have you noticed how long took it till you did so of course we can combine this with something better but that we've seen before and could use similar syntax as in case ranges now for indices so again left and try to inclusive and we assigned the same value to all of these values indices and we can also meet the size again because we have we can deduce it from the biggest index and we can mix and match those as much as we want there's only one restriction both the index and the value have to be constant expressions and that's it so here naturally the F has to be constant and it gets assigned to index 3 and the hundred here gets the index 8 and the array in total is 21 elements so speaking of a race to explain the next one I would have I have to dig a bit through the language and try to implement something that will be down a pain path of pain imagine the following many virtual machines or scripting languages or systems like that have immutable strings so those are strings once they create it they cannot be changed in size they cannot change in content and so because strings are used a lot which these implementers of these virtual machines try to make them as quick and as accessible as possible and many times also put in a hash table so you don't have to placate strings in your system because then a string comparison is just a pointer comparison which is a lot quicker than comparing strings then they probably garbage collected or reference counted or something like that and so I want something like a share point of a vector of something okay I'm gonna generalize this to not just strings if you create something like this in C++ we get a memory layer to do something like this they each block represents its own allocation we have the control block here which contain of the reference counting in the internal bookkeeping of the share pointer that is something internal that we don't have access to and I think it should be common knowledge now that with make sure we can fuse those two locations into one but I want to go even further I want everything in one allocation because the size of the data doesn't change but I do not want this indirection I do not want access to this something that then has a pointer that points to the data I want to go a pointer to the Container just a constant offset and find the data what could be used for this what's the question mark but there's nothing in the standard library can you tell that but there's something in boost it could help us you boost as a container called static vector you give it a template constant integer and it call it's going to create a buffer for this number of T's inside itself so it's kind of useful because once we have a pointer to the static vector we know exactly what to do to just get to the data because it's right next to it so we do not have an indirection that's great but the fixed capacity is a problem because if we create less than n elements we gonna waste memory if you create more well we can't because it's a fixed capacity it cannot grow well there's another container that works in a similar fashion it has the same starting position so again no indirection if our size of the container is not more than n but as soon as we grow beyond n it's gonna just turn into a normal vector and again have an extra direction and we are also wasting all this memory here because the vector is to store all it's a tiny contiguous block you cannot just split it in half so what do you do when Oh buddy ass off the problem yet you do it yourself and let's try to do just that imagine here a visualization well you don't have to imagine it you can just see it I guess a visualization of our memory allocation right on the far left is the lowest address of our block of memory and just keeps growing as much as we need well it doesn't prove dynamically rated ones we also have this thing that represents the question marks the thing that we interact with that has a known type unknown size we know where it is we have a pointer to it it is the T in our set pointer I'm just going to call it a header here and it knows how many how many elements there are I can ask you to give me a integrator to the data and so on the layout in memory would look something like this I have my header structure at the very beginning and then just an array of data in this case I'm going to demonstrate it using doubles to create this we need to know how many pints bytes to allocate and that is kind of straightforward we have the size of the header and then enough space for n elements and then here is a runtime value you do not know it at compile time that's the assumption you're making here then of course I just allocate bytes I construct the head object I construct your right and then later down the line I'm gonna just use the data right and then you do this two things may one works fine cool and the other is you're gonna crash with righteous fury because you dare to it unaligned loads and stores because many architectures where I guess most of them require that your doubles are aligned on an eight by boundary if you run an arm that is your world that is the reality on an x86 it's kind of optional so it depends on what instructions your compiler is going to generate if it generates unaligned lots and story is fine however if you also want to support order our CPU architectures it can be up to two to ten times slower to iterate through this array if it's not aligned and if your compiler decide to use aligned instructions well just go home so to fix this we need to sound add some kind of padding behind the header to make sure that our double is aligned on an eight byte boundary which looks like we just need some kind of offset like the size of the double but okay double is the example here but it may not be a double so really we want the alignment of the type but if you now add something to our header it's may grow beyond that of a double so began I had overlapping data structures and they just yeah don't go there so let's try again we know that we need at least in our files to store one header we need at least enough bytes to store on alignment then we need at least one less bite we divide by the alignment of the table okay and then we what okay so if you do not know this pattern this is how you round up a positive integer to the nearest multiple of another this here is a integer division that rounds up instead of down which is the default for positive numbers and then with the multiplication we can then turn this into a rounding up towards the multiple of another integer of course we could use some bit twiddling tricks because we know the alignment is a power of two but it happens at compile time who cares so we have this X now you're gonna plug it into the code we had before and everything's fine except it's not this one line okay this one line this one innocuous line is a massive massive troll by the community it's in who's gonna drive you crazy it's like you know sometimes this line just works sometimes it doesn't sometimes gonna crash your program sometimes about seven it's gonna corrupt your memory sometimes it won't you just connect angry right angry at yourself because you think you don't understand this one damn line of code that's so obvious it couldn't be more obvious what it does and then you get just angry at the compiler because I think it's breaking your code but no it's just doing its job you just got C++ why are doing this to me I thought we were friends no no we are not friends no no I think you just get sad you realize this there is no code at the end of the rainbow the pot is full of crap and you just have to carry it around with you because let me tell you this is why the committee hates you let's have a look surely at working draft comma standard for programming language C++ section x4 don't new paragraph 19 and there's also a link as evidence if you want to verify yourself you look at this section and come across this it explains how the array expression with arguments is converted into a call to an allocation function which is also called operate on you because sure I know so it shows that here you have these two parameters that get passed into this operator and they just get appended at the end of this education function and then overall resolution is going to pick the best match this is what we do every time we use placement new where we have this pointer where we want to place our object and then it resolves to the built in allocation function that does nothing essentially except do you see what I see what is this who is this X where's it come from do you see it in your rendering expression on my plant well so you'll keep reading on and you come across this lovely paragraph so let me read to you a horror story here each instance of X non-negative and specified value representing array allocation overhead the result of the new expression will be offset by this amount from the value returned by operator new this overhead may be applied in all Iranian subjects new expressions including those referencing the library function operator new with the signature that we are usually calling in this case and other placement allocation functions the amount of overhead may vary from one invocation of new to another what the hell is this let if you don't understand the code that the language is written in or specified in let me summarize okay they say non-negative value that is added by the compiler every time you call an array new expression in the array form and this value made may vary from one new call to the other and you don't know the value there is no way to carry this value in advance you don't know it and so if this one one single message from this talk that you keep this is the serious part never ever for whatever reason use the array new placement version of the built-in operator just don't it will corrupt you memory it will corrupt your stack it's a door for attackers because there is no guarantee that you can actually create a buffer that is guaranteed hundred percent big enough to hold the result of this expression there is not so if you like me you're thinking this right now and really it's those moments where we realize the committee is just out to see you suffer because they strive on ultimate despair so let's see if we can salvage this we know the problematic line and we do have a solution kind of which is in C++ 17 we have the uninitialized algorithms so in this case you can use initialize default construct n it takes a forward iterator and a number and it's going to construct an object at every position that the iterator points to and this is another thing I'm like what the hell is this because think about it this algorithm gives an uninitialized wrong storage and yet we have to give it an iterator to objects that don't exist yet what the hell who designed this evil people did that's the answer well it is what it is but there's one thing I still don't like about this right you have this buffer here so if we imagine that this is like capsulated in a factory function or something like that then we only really want to return the P the pointer to the header the thing that we're actually interacting with so we need to base everything off of this pointer P which is easy right just turn it into a point of the bytes at the offset turn it back into a point of doubles and we're good fortunately you're not because again you think you know what you're doing you think your programming against the cpu but you're not you're programming against the abstract machine in the abstract machine you can just take any arbitrary pointer add some number to it and say professor Pablo because the compiler knows that this pointer has been created from one single allocation it knows that it doesn't point to more than one thing and that's why you cannot do this and that's that's that's a trap that well I mean this reinterpret cast all over the place you know that something's wrong but this is one of the things that many people remain - it's a big source of a different behavior traps and it's just you know this conception that you're not writing you're not programming the CPU you're programming the compiler so we have to do let's just store the buffer pointer because that is actually something that has allocated storage for other things and so we can use that as our starting position for the reinterpret cast and this short work big emphasis on should because P is something or buffer is something that is actually part of the allocation and constructing chain of those doubles so are we good now who think that this is all it is wrong it's more in fact this entire thing it's just it's just on different behavior cut just throw it away because see you're trying to treat this pointer as if it was an array but it's not you have never created an array the way initialize default construct is specified it is just places objects individually somewhere in this case they just happen to be next to each other in memory but that does not make them an array that's not how the language works it's how the rest of the world works but not the language so yeah index zero sure that reference is the double that was created there this dereference is the past the end iterator and this is just just garbage it's nothing so really really yeah unfortunately I believe that there is no way to implement this in standard C++ in in the efficient way that I wanted I challenge you to find a way that doesn't have any undefined behavior I would like to see it but I don't think there is one and so if the standard doesn't help us they just throw it out the window and create our own rules which is what the people at GCC did so we start again with our header structure and this time we are going to add an unsigned array and this is the thing that is called a flexible array member it is an array with outer size and this instructs the compiler to alter the alignment and the size of the structure in a way that we can use it exactly for the purpose that we wanted to use it's almost as if it was created just for that and now our intuition holds now we can count the number of bytes the way we wanted to now it works to just allocate this array now it works to just place menu this header now it works to just construct these doubles because when we access the thing now we're actually accessing it through an array object the compiler knows what we want to do the compiler knows that there is an array following the structure and don't be alarmed by this thing in this truck right this this is just symbolic data does not occupy any space in the structure it only instructs the compiler to do some point arithmetic to access the first element distracts the size of this head is still 8 there is no pointer in there or anything so we have the solution we of course should clean up after ourselves just use smart pointers which I it shows not to to demonstrate what's going on here you can move that in destructors and constructors and so on I'm sure you can figure out how to do that what we haven't solved yet is the sharepoint apart and unfortunately we can't go further there because we don't have access to the type that share pointer uses for its internal bookkeeping I would really like to just you know slap the thing at the front of the buffer here and construct the share pointer with a pointer to this control block and tell it hey here it is take ownership it's not used you manage it with Reb common everything but we can't we have to implement it ourselves I won't go into that here but a useful tool to look for here is boost intrusive pointer it's very useful and it gonna make your life a lot easier well that's so far it for a race let's go to something new and this is the part where either gonna hate me or love me because it's going to use a language feature that people either hate or laugh or love to hate and for this example I have created a like a very trivial bytecode language that should consist of these op codes and it is very simple each instruction just takes the current value and does an arithmetic operation with the constant right that's all there is to it and an interpreter foil is also very trivial tube right and it's just a switch inside a for loop it always it reads the instruction and advances the point and execute the action that is associated with this instruction right so the add one here is literally just creating this action and when we reach the hot code we just return the value that we've computed okay I've been chucked this and this is mostly just for reference so what I did is just create a uniform distribution of all these op courts except for the halt code because I want my benchmark that she run to all the way to the end and then I slap a halt at the end to make it terminate so you run this you get some numbers out of it they don't really matter for now but what does matter is this do you believe that you can make this faster do you think that you can refactor a switch inside a loop that is so trivial and still make it faster because that's what I did and we have the numbers for it here and here is the speed-up so let's throw away the first one because it's an outlier but for the rest of the cases you have on average 15% fast execution doing the same thing and the way we do it you can see it in the name of the benchmark it involves go to which is also where this feature is called computer code I think we all know for how go-to works right that the body of this function is just a for loop but what we can do now what's new is that we can take the address of a label using these double ampersands we can store the address of a label in a variable and later you can jump to that address those are good reactions in so notice that technically yeah it looks like we'd be referencing a void pointer which we cannot do which why I say that this asterisk is part of the go-to it belongs together it should be treated as one keyword and you also cannot refactor this object or function the asterisk has to be with the goal and this enables something that we've never had we can now write indirect jumps that is a privilege that up until now has been reserved solely for the compiler we have always able to do indirect calls with function pointers but this is new because now we can create jump tables that are just as efficient as the ones by the compiler we can use a dynamic index to access an array of labels and then jump to one determined at run time and I mean yeah so far this is only been C so he can make the array constructs bridges because you know but the thing is you know notice that we are just jumping to a void pointer there is no specific type for label addresses so an evil person or a very clever person depends how you see it could just pass a void pointer that is the address of a label in one function to another function and then have that function jump to that label so you would have control program from the middle of one function to the middle of the another function and that is where food cans look like toys but maybe it's useful to someone if they manage to not break everything so let's see how we have way now this is this is the tool I use but now how did I actually apply it so I did very volatile things to my route in fact the loop is gone so I create this table of this jump table full of the addresses of labels every instruction has and label associated with it and the rest of the function just has lots of labels each label execute the instruction and then does the same as the top of the switch did it decodes the next instruction and jumps to that entry in the ROM table so we have a lot more labels like this you also f1 go to at the top so we know what the first instruction is to jump to and because I hate repeating myself I just put it in a lambda and this is again the point where you cannot put the asterisk away from the go-to it has to be there so this is the how but it doesn't explain the why why is this faster there is no loop there is no switch and this is also sometimes called threaded jumps because it essentially you're jumping from case to case to case the case you're not going through the top at the switch so to understand why this is faster let's have a look at the assembly this is the simplified version of the switch if you see the top two instructions here they just read the next instruction increment the pointer right and then we have the jump and we see that it has this operand a register so the destination of this jump depends on a runtime value and it can go any one of these labels which are representative of the cases then if others jumps they just go back to the top those are the breaks in the case let's compare this to the go-to and for first we see there's a lot more code and in fact this function is about 20% bigger than the other but there's a lot of repetition here right those blocks already really different the top line which is the arithmetic operation that we encoded in our instruction set and the rest is character for character identical for every block in fact it is almost a drink'll to what the compiler created with the switch with the only difference the compiler he generated its own jump table whereas we brought one ourselves so the compiler already had the right idea if you get out the case goes from 0 to n contiguity contiguous and it can implement this with the jump table but it's not fast enough so the jumps here pretty much the same as in the other example and they cannot jump to everywhere and these are indirect jumps right that's why the arrows I read because indirect jumps are generally bad for the CPU because complicated architecture reason asked Network board he tell you everything about it but so the first intuition would have is you know I have a lot more indirect jumps it looks like it should be slower to see if you should have a harder time predicting these jumps so to explain why this works let me first summarize what actually happens before I go into the why so if none of this assembly mumbo-jumbo actually means anything to you this is the explanation of what's going on the CPU has recognized patterns in my randomly generated input let that sink in the CPU can analyze my data that's randomly generated and find patterns in it to understand how that works let's have a look at a much simplified example so now we reduce our instructions at only two values a and B and we produce an input that is alternating between a and B forever we also have the reduced implementation that only deals with these two bar labels and if you look at what's going on here now we have we see that this one jump here has a 50-50 chance to go either to an A or B so what happens from this abuse perspective here is it starts its season a said ok we're gonna jump to da then the next sits it thinks well I just went away so clearly gonna go to a again but no B alright next well I just want to be so clearly B is the most likely next candidate not wrong it's a next one come on now I've jumped to a twice ok B only once clearly a is the winner here not you're wrong it's V now so we have a 0% branch prediction right here now it is not 100% true because some CPUs can actually detect this specific pattern but it depends on your architecture it depends on the model and everything so in the general case if you chip you is not able to predict this kind of alternating pattern this is what's gonna happen well it's in the other case it's a lot easier we know 100% that every a is followed by and B and we know that every a every B is always followed by an A so here the prediction rate is 100% every time and it's a huge speed-up of course the numbers that I showed you where just for this you know toy language so let me show you a real application of this I chose Lua for this which is a very widespread scripting language and it is also an interpreted language it is not computer compiled to bytecode to machine code it is implemented in C and it also has this switch inside a loop and the creators of were actually smart enough to create macros that let you modify the beginning of the loop the switch the case and the break so we can change how the main core interpreter loop actually works which is exactly what I did so I compile two versions of Lua one with a switch one with a go to and I ran a benchmark on it seemed our course I'm mark I'm not sure but it's a popular benchmark that is used to make Lua implementation compete against each other the real the numbers we only need to care about other ones on the left which show the average mega flops per second then we also have numbers for the go to and then we put them next to each other and this is this incredible speed of up to 41 percent depending on what you do the fast Fourier transform is very compute heavy so making an interpreter run faster won't really matter much and it doesn't because you compute bound but the Monte Carlo integration does a lot more of other things and speeding those up works and on average all the benchmarks together manage about 20% more mega flops per second and that is a huge win I mean and Rewa is not the own example so the people at C patent did this too and they noticed an up to fifteen fifteen to twenty percent speed-up of the virtual machine right this is performance lying on the floor you pretty much do this very mechanical transformation of you know code that can speed up all your Python programs by twenty percent that's insane and the committee does not want us to use it and rupee also uses this go-to and dharak the JVM on Android does this too so in the in the free world it is not a secret but in C++ it's it's it's guarded so I've just showed you lots of things that you you know you technically cannot use and I've been told by committee agents in this building that they don't exist but if you leave the bubble of the committee you realize that a lot of compilers actually do support them these are the oldest compiler versions that I contest on compiler Explorer and in fact the youngest compiler on this list is from 2012 though if you are on Windows it's kind of you know Microsoft with a big conformance Porsche that just did they just don't want to oppose the committee anymore it's just you know yes yes we do as you say but and you're not a corporate drone you're just gonna use prank on Windows problem solve right okay so now let's let's let's go back to serious mode because it's all the fun and the left and everything in the jokes this matter is real because you know there's the C++ slack you know if you know it and I'm one of the administration administrators of this slack and one of the agents of the company approached me there they came to my turf and threatened me here's what happened they asked me do you see me as the enemy duh one your French and your nature of the community so I said that they're French because actually you know who this is so I did a bit of a mind trick career so I let them know that I know so that they know I know you know and then they say well you know if I were an agent of the community I might declare up in you B of course that's what committee members do you know if they don't like something they call it undefined behavior just stops existing problem solved so I already assumed as much but the next thing they said that actually that blew my mind and it should Rose used to because they said allowing me to optimize your existence are very attractive think about what this means this agent of the committee has just openly admitted that the committee is access to time travel technology you know the next time you see a conversation between a committee member and a normal person and the normal person says something like well you know I don't like this part of the language and this is so this is dangerous can we change this and remove that what is the canned response well it'll only be at the time machine code may contain things so I hope that you are now as enlightened as me that you understand the danger you're facing here because if you thought that you Minotti a bet just think about this you have this multinational organization backed by governments backed by our text money that has access to time travel technology that is controlling all of C++ everything even this laptop here so you think this is Windows just gonna lose Linux and open mrs. her but it's see it's the same thing they all working together you can't escape it so you have to fight it and so I hope that you will join me on the rebellion of the free thinking C++ programmers and crush the tyranny of the committee and you know I'm really glad that all of you in fact stayed all the way to the end I know that I may have come across a bit crazy at times I'm not crazy I'm not crazy don't call me crazy but now that the truth is out I can finally stop living in fear and that's it [Applause] [Music] so if you have any questions please gather at the microphone oh yeah look at them this is what I'm Reba this is what an evil person looks like yeah maybe I haven't evil suggestion or hiding your name place the question is wouldn't that be a big chance for better optimizes through to translate form these switches to the mechanics that you explained with the computer I asked myself the to and in fact when I gave this in meetup in the munich meter one attendee said that some compilers do it on arm but i don't understand why i clang OGC don't do it on their own maybe there are trade-offs that I'm not aware of because it also does increase actually your size of the function so I don't know why they don't do it but they should if they can have you figured out all the options of the optimizer that you might be able to set how many other again I don't know I never try those but maybe it's already implemented nobody knows yeah yeah good question to ask someone else at this conference I guess I'm a bit conflicted because I look after GCC so the side of my t-shirt the the reasoned compiled it doesn't do that switch expansions you might have expected I think is probably because the actual switch code generation happens much later in the compiler than it could make that decision okay that's unfortunately white and we also have and we have the labels extension and everybody writes their code exactly how you described it so it's got that extension to now it's not undefined behavior it's ill-formed which of the many slides ahead I think all of the all of the slides were ill formed and what you're relying on a vendor extensions except that once where they didn't most of the flexible array code on the slide was not a relying on extensions that was full of undefined behavior instead the the way you showed it yeah with with the flexible array as a vendor extent sure with the flexible array but everything before that okay all right oh yes I had to thought about that one okay if you could go back to that slide you mean this the slide where you actually had the flexible of RAM you had the destructor in the header okay that's this that one you could put the constructor in the header and put the uninitialized default construct in that constructor I did mention that you could put things in and make it look a bit neater yeah yeah I agree I have a question about slide nine which was the anonymous struct you mentioned that a committee member would say that there's undefined behavior and I was wondering where this one yeah yeah so the undefined behavior comes but one okay it's actually in form because if the structure but even if it had destructed a name and the field name will be undefined behavior because an array in a struct don't have a comment common initial sequence why not because it doesn't i-i've looked at the standard and I confirmed with another agent here that in fact whenever the standard talks about common initial sequence it is between arrays or between classes but never across okay okay I think that's the best answer I have I don't know why hi I just wonder how did you discover all those Easter eggs in the language well some of them I just by accident just I happen to read about them and then I thought I maybe there are more I should make a talk about it so I did and they I in fact many more but the majority of them only really applied to see and are obsolete in C++ so yeah what I didn't mention a lot of these extensions are actually for made for C 99 but you can use them in C++ mode thank you now there's another one remember his face so apart from the fact that all the stuff either is on different behavior or doesn't exist some of it sounds like it's a very good idea and obviously if you also have existing practice and implementation experience so one know why a lot of these things either have not been proposed for the standard or have been rejected by the committee somewhere in the distant past do you know anything about kind of so I about two things what I didn't show a variable-length erase those there was a petition to declassify those but the committee decided that we are not prepared for that kind of power and they were I think in Cologne there was a paper discussed about flexible remembers by Nicole massacre but I think the conclusion there was because they did also change some things they added more C++ lifetime semantics to it and so they asked for implementation proof of concert implementation that's the one only the two I know I don't know if others were proposed before that yeah maybe we should dig a little bit in history and you know maybe some of them can be either resurrected or just never have been proposed maybe yeah okay that's it then thank you all for coming and this [Applause]
Info
Channel: CppCon
Views: 65,909
Rating: 4.96351 out of 5
Keywords: Miro Knejp, CppCon 2019, Computer Science (Field), + C (Programming Language), Bash Films, conference video recording services, conference recording services, nationwide conference recording services, conference videography services, conference video recording, conference filming services, conference services, conference recording, event videographers, capture presentation slides, record presentation slides, event video recording, video services
Id: IAdLwUXRUvg
Channel Id: undefined
Length: 52min 22sec (3142 seconds)
Published: Tue Oct 01 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.