Switch IS NOT FASTER than if, (in C++)

  Рет қаралды 55,576

Low Level Game Dev

Low Level Game Dev

Күн бұрын

Пікірлер: 478
@cFyugThCzvAqYaGmxRgfCKTuvHMEjQ
@cFyugThCzvAqYaGmxRgfCKTuvHMEjQ 4 ай бұрын
Thank you so much for making this video. I worked on LLVM and Low Level Learning's video on this topic drove me INSANE since I worked with the exact bits of LLVM that optimize ifs and switches to jump tables and similar. Unfortunately, Low Level Learning has plenty other misleading and harmful videos, and not just him...
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yooo this is so cool, if you want to, you can dm me on Discord or tag me in my server (link in the description) and we could collab on a video about other compiler optimizations stuff. let me know if that sounds cool for you
@mixed_nuts
@mixed_nuts 3 ай бұрын
Not every language uses LLVM...
@johanngerell
@johanngerell 3 ай бұрын
@cFyugThCzvAqYaGmxRgfCKTuvHMEjQ Then you should mention what he did that caused the unexpected result, because he *did* measure, right?
@Ether_Void
@Ether_Void 3 ай бұрын
@@johanngerell Giving results without showing the methodology is bad practice so it should have been up to LowLevelLearning to show things like compiler version and flags that where used. But if I have to take a guess, from the assembly it looks like it was made in debug mode and not as a release.
@tutacat
@tutacat 2 ай бұрын
It is hard
@sledgex9
@sledgex9 4 ай бұрын
I 100% agree with the "code readability and maintainability instead of chasing dubious optimizations" mentality. However, I fail to see how multiple chained ifs are more readable than a switch.
@LinuxVeteran
@LinuxVeteran 4 ай бұрын
I could see an argument that when looking at a sufficiently big switch statement, the specificity of multiple else-ifs could be easier to interpret in an unfamiliar codebase. Since to find out what case is being tested, you'd need to scroll up to the top of the switch, then back down to the specific case. If statements also leave a larger footprint on the line, and are easier to search if you're trying to search your code for checks against that variable.
@TeslaPixel
@TeslaPixel 4 ай бұрын
Yeah, I can much easier parse the switch @ 7:51 than its matching if
@theevilcottonball
@theevilcottonball 4 ай бұрын
Especially my unreadable version, where I prefix the case labels with break so they don't fall through, looks weird to others but not to me.... switch (a) { break;case 1: foo(); break;case 2; bar(); break;default: baz(); }
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
idk personal prefference. I like to type less
@LaynaStambaugh
@LaynaStambaugh 4 ай бұрын
@@lowlevelgamedev9330 Then why not use switch statements? You *do* know that switch statements are typically reserved for comparing many upon many different potential states of a single value. Example; // Starting code enum color { green = 0, blue = 1, yellow = 2, purple = 3 } std :: srand(std :: time(nullptr)) color myColor = std :: rand() % 4 // So... how is THIS... switch(myColor) { case(color :: green) std :: cout
@LuisCassih
@LuisCassih 4 ай бұрын
So, yandere dev already knew to trust the compiler, he was ahead of his time.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
smartest programmer under the hood actually 😌
@bahmoudd
@bahmoudd 4 ай бұрын
​@@lowlevelgamedev9330 not smart enough to know the age of consent
@ITR
@ITR 4 ай бұрын
He had nested if statements and string based checks, so not sure a switch statement would've actually helped him. Though I also suspect old versions of the mono compiler didn't have this optimization
@xorxpert
@xorxpert 4 ай бұрын
@@ITRone thing that killed me was function IsOdd(int num) { if(num == 0) return true; else if(num == 1) return true; else if(num == 2) return false; // … }
@sagitswag1785
@sagitswag1785 4 ай бұрын
He was programming in C# not C++
@LinguisticMirage
@LinguisticMirage 4 ай бұрын
here is my 2 reasons why i still use a switch case: 1. you can be 100% sure that compiler understands what you are trying to do. 2. it CAN look cleaner than a if statement
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
If you like it more sure, but you can be 100% sure that the compiler will also optimize ifs. I have done tons of tests
@tiranito2834
@tiranito2834 4 ай бұрын
​@@lowlevelgamedev9330 Exactly. If the if statements are performing an operation that could be optimized with the equivalent switch statement, then the compiler is obviously going to be capable of applying the same optimization. Modern compilers are programmed to be able to do this. And with modern we're talking about quite a few years old actually so yeah... lol. In any case, switch and if both exist for a reason. If you're building something that is going to give equivalent assembly output due to its nature because both can be optimized into jump tables, then I would use whichever option makes it clearer what is it that I'm doing. At that point, it just becomes an stylistic choice. If I'm doing parsing or some kind of similar operation by hand and building my parser from scratch (or building a bytecode interpreter or statemachines or whatever), then usually, for specific cases it makes more sense to have a set of switch-case statements, and then put into the default case any operation that cannot be computed into a jump table due to the nature of the computation required for the condition in the if statements. That's how I work at least, and I believe it gives a pretty clean style, as well as allowing the code to stay optimized even when compiler in older targets, in platforms with ancient compilers that for whatever reason did not implement this optimization.
@fuji_films
@fuji_films 4 ай бұрын
Well, just don't use branches at all. Example: return a*(a>b) + b*(a>b) is better than if (a>b) {return a} else {return b} And performarce will thank you.
@ItsCOMMANDer_
@ItsCOMMANDer_ 4 ай бұрын
@@lowlevelgamedev9330 msvc optimization fails (you mentioned at 9:25) left the chat
@cyanmargh
@cyanmargh 4 ай бұрын
@@fuji_films compiler probably will optimize a>b?a:b out too to something like a - ((a - b) & ((a - b) >> 31)) or even will use platform-specific branchless codintional instructions like CMOV. you really underestimate how powerfull modern compilers are. The real thing that you actually should take care and where compiler is hopeless (in case of c and especially c++) - memory management, rare branch prediction/cache stuff cases and general logic of algorithm (For example, in my game, when rendering space, I divide stations into “far” and “near”. During the first pass of the array, I draw the distant ones as points, while I draw the near ones using full 3D rasterization. Initially, I sorted all the stations by distance from the ship, and then drew in descending order of distance to the camera, but then I replaced this code with the following and everything began to work much faster: 1) draw all the distant stations, and add the nearby ones to the temporary list 2) sort only temporary list and draw in order of decreasing distance)
@otrqffaimajg
@otrqffaimajg 4 ай бұрын
i need to trust him, he sounds like a Russian hacker.
@thebrowhodoesntlift9613
@thebrowhodoesntlift9613 4 ай бұрын
That accent doesn't sound Russian, maybe Italian? South American?
@eetukuru787
@eetukuru787 4 ай бұрын
@@thebrowhodoesntlift9613 Romanian.
@Roop-n4z
@Roop-n4z 4 ай бұрын
He is from the city of Rome, Romania, United States of Russia.
@ThatTanishqTak
@ThatTanishqTak 4 ай бұрын
This made me laugh.....
@insu_na
@insu_na 4 ай бұрын
He uses Ukrainian colours for his bar charts Edit: he's Romanian tho. I guess blue and yellow are also in the Romanian flag, he just didn't use a red bar chart
@_emik
@_emik 4 ай бұрын
In C#, the compiler does automatically convert if's to switches if appropriate. In fact, it sometimes does the opposite in scenarios where it is deemed superior, such as reducing the size of the function which helps the runtime optimize call sites more, or within string comparisons.
@chakibchemso
@chakibchemso 4 ай бұрын
JIT for the win! Or maybe just RyuJIT, jvm sucks 💀
@DFsdf3443d
@DFsdf3443d 4 ай бұрын
You misunderstand why we say switch is faster than if. Sure if statements can in some cases be optimized to be equally fast as switch statements, but that is not guaranteed. The difference is switch statements put a constraint on the programmer writing it. They force them to evaluate based only on integer like types such as char, int, or enum. You cannot switch on more complicated-to-evaluate datatypes such as strings. This is why switch statements are guaranteed to always produce jump table lookups or something better. An if statement, on the contrary, can produce something much slower in the worst case scenario because it doesn't have this constraint. With if statements a programmer may be inclined to try to evaluate based on string comparison for example which is much much slower. That is why we say switch statements are faster than if statements. They force the programmer to keep evaluation simple, which *is* faster. You are correct in that you can always derive an equivalently fast if chain from a switch statement (this seems to be the focus of your video), however you may not realize you cannot always derive an equivalent switch statement from any if chain. Essentially it's the same reason you'd say constexpr if is faster than regular if. Even though the compiler can usually optimize a regular if, that evaluates only compile time data, to be the same as a constexpr if. One is guaranteed compile time evaluation, the other is not.
@bloom945
@bloom945 4 ай бұрын
They also force you to be exhaustive and cover all cases
@Brad_Script
@Brad_Script 4 ай бұрын
switch are faster than if (if you have a lot of cases), the compiler literally replaces ifs with switch with optimization on. The title is misleading.
@slyfox3333
@slyfox3333 4 ай бұрын
@@bloom945 No they don't. The compiler will happily accept a switch statement without all cases covered and without a default case.
@DistantJacob
@DistantJacob 4 ай бұрын
@@slyfox3333 Appending to this reply, some languages (actually Java's the only one I know for sure), will warn that a switch statement does not exhaust all the options of an enum. That said, the programmer can just ignore the warning. Reply is still right.
@pierreollivier1
@pierreollivier1 4 ай бұрын
@@slyfox3333 yeah in trash language but in any modern language you need to be exhaustive
@SimGunther
@SimGunther 4 ай бұрын
TLDW on an optimizing compiler, the distinction isn't too important, but for non-optimizing compilers and interpreters, it actually matters to use a switch statement/expression wherever appropriate.
@segsfault
@segsfault 4 ай бұрын
Exactly!
@kodicraft
@kodicraft 4 ай бұрын
If you're using a non-optimizing compiler/interpreter in code that cares about speed, you have way bigger problems than if vs switch
@MrDavibu
@MrDavibu 4 ай бұрын
​@@kodicraft Can be important for proper debugging/breakpoints. While you could optimize some parts of the code and debug the rest, you would need to turn of the optimization for full debugging. So having code that excutes fast for non-optimized code is more convenient.
@sagitswag1785
@sagitswag1785 4 ай бұрын
​@@MrDavibuwhy? You would never turn off optimization fot actual production code..
@yellingintothewind
@yellingintothewind 4 ай бұрын
@@kodicraft Never done embedded work? I sometimes use a rooted kindle paperwhite when working in direct sunlight. My compiler is tcc. And the device is so low powered that optimized code is crucial.
@marinesciencedude
@marinesciencedude 4 ай бұрын
Does the universe explode when two KZbinrs with 'Low Level' in their name appear in the same video? probably not but the frequency of such a naming scheme is curious
@toyb-chan7849
@toyb-chan7849 4 ай бұрын
To 9:25 : At least in the case you've shown on screen, MSVC isn't "failing" to optimize the switch statement but has most likely decided that maintaining a jump table is not worth the cost (perhaps of potential cache misses? who knows for sure.). If you add some more cases, MSVC too will employ a jump table eventually. Or at least that's what I have gathered from playing around with it.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
oh I see, interesting. Thank you
@hyde4004
@hyde4004 3 ай бұрын
Once more confirming that, indeed, optimizations are hard. Quite honestly this is some PhD level shit, I would only really trust info from a good book or maybe the people literally deving GCC / LLVM or something.
@Kuukunen2
@Kuukunen2 3 ай бұрын
Hi. C++ game dev here. I appreciate the idea of the video, but unfortunately there's many things wrong. First, the explanation of jump table as an array of function pointers is misleading, at least when it comes to switch statements. You could argue it's for easier explanation since C++ doesn't allow for actual jump tables (unless you use non-standard extensions like gcc's Labels as Values), but you should at least explain that, since it makes it look like switch statement compiles to function pointer calls, which would be pretty counterproductive. Second, the whole benchmark is kind of invalid. Calling rand will overshadow any low level switch/if optimizations. It doesn't affect the result, as you can see from the assembly, but it makes the charts and timings completely meaningless. Or since you're testing such low level stuff, another potential inefficiency is the modulo operator, which can be surprisingly slow. Although I'm pretty sure since it's a constant here, most compilers should optimize it even if it's not power of two. (Side note, the assembly doesn't have div at all. Since they're constants, even the inefficient divisions get optimized into crazy bit-trickery multiplication instructions instead. It's pretty cool, but off-topic for this.) Third, the problem with all these "the compilers are smart" statements, is that a lot of the time they fail in unexpected ways, ESPECIALLY if we're talking about a somewhat recent thing that is clearly non-trivial. There's been decades of "you don't need to do X anymore!", that then end up not getting optimized in some cases. I'm not saying it's for everything, like ++i vs i++ is probably optimized... or *2 into a bit shift. (Although, what if i is actually some weird iterator class with operator overloads? It's C++ after all...) Sure, you proved that this specific function is the same on this specific version of this specific compiler on this specific platform. But what if you add some fall-throughs and if statement in a default case? Will it still optimize it? What about MSVC? Can you confidently say all the optimizations work the same on ARM as well, on all the compilers? Not so sure anymore. Mobile is a lot better these days, but they used to lag YEARS behind the trunk of GCC/clang. And since you're making game code (I assume), what if it gets ported to Playstation or Switch? They use GCC/clang as well, but generally they have their own modified versions that are based on older stuff that might even disable or lack some optimizations. Another thing is that sometimes you need to help the optimizers. I've seen a lot of things fail to optimize because, for example, there was too many layers of function calls, even if all the function calls are very simple and should be all inlined. In very simple toy examples it might not matter, but in real code, things can get a bit more messy and the optimizers can get confused. Check quick-bench bW4DybP8d8RbBFkV6ReJcfFOlYA for example. (I'd link it, but I think my comment would be eaten.) On clang, even that slight modification makes the optimizer confused. Interestingly, on GCC it still gets optimized, though. Pretty sure MSVC would fail, but I can't be bothered to check. I'm not trying to diss the LLVM/clang guys here, though, optimizations are hard. But the main point: it's dangerous to make statements of "you don't need to do X anymore!", because there are so variables and edge cases, and suddenly your core loop is x2 slower. You also can't just hand-wave away MSVC. I know a lot of people would rather pretend it doesn't exist, but if you're making general statements about C++, especially about game dev, you either have to take into account MSVC or title your video "switch statement is not faster than if (in C++, on GCC or clang)". That would still be wrong though. Maybe "(in C++ on newer versions of GCC or clang on x86, in simple cases)". Of course saying "switch statement is faster than if" is incorrect. But so is "if statement is just as fast as switch". The real answer depends on your specific case. I think these days most people use switch statements for the readability anyway, but even if we talk about performance only, one main benefit is that even if the compiler WAS super smart, the switch statement will force you to refactor your code in an efficient way. A lot of the time the statements are a bit more complicated than just 11 numbers from 0 to 10, so switch statement can be good because you simply can't make an unoptimizable if-else chain by accident. A lot of the time I get into a situation where I'm thinking "I mean... the compiler SHOULD optimize this, but will it?". So I have two options: 1) Spend time with extracting and compiling the code to profile or check godbolt or whatever. 2) Just use the just as easy to read and write version that I KNOW will get optimized. Edit: oh yea also, as a tip, you can use volatile to force the compiler to not optimize some variables for testing. Just be careful, for example if you make nr volatile, it would make the ifs a lot a slower, because it would be forced to check the variable on every statement per standard. Which could in theory also be a counter argument for switch vs if, but volatile is not super common. However, it could be some other thing, like atomic. Which would be another layer of cognitive load for deciding if you want to go with switch or if.
@luciferzero8164
@luciferzero8164 3 ай бұрын
Nice.
@painsama2791
@painsama2791 3 ай бұрын
Lmao​@@luciferzero8164
@aleksanderwasowicz8499
@aleksanderwasowicz8499 3 ай бұрын
The whole "let's assume -O3" bothered me a lot. Code should be good to begin with, -O0 is the only valid chose to say what's faster. Many optimaziations are re-run (see for example -frerun-cse-after-loop). To waste optimaziation cycles just because one can is insane (will result diffrent outcames). The whole idea that optimizer will run until it can't optimize more, is just wrong. "There are no free abstractions"
@tirushone6446
@tirushone6446 3 ай бұрын
As project (not in c++ but in rust) I have been writing a wasm runtime, which needs to interpret byte data as instructions, and I have serveral match stantments that match on 200 + values and then sometimes each of those will match the next byte and produce the next intruction to be exacuted. For that project having one big match statment would probobley be really fast, but it would also take up 1000's of lines and be difficult to work with, so yeah real world case can get much more complicated the just 10 or 80 cases.
@sadasd-n2f
@sadasd-n2f 2 ай бұрын
@@tirushone6446 “Case Number 999:” lol just imagine
@markuspfeifer8473
@markuspfeifer8473 4 ай бұрын
The real reason to use switch is enums. Adding or removing a case breaks things. And that’s a good thing bc it forces you to fix code that might otherwise break at runtime
@Brad_Script
@Brad_Script 4 ай бұрын
It's not because it can break things, it will break with if/else if too. The reason is because the compiler can detect if you remove certain cases if you don't have a default block.
@ITR
@ITR 4 ай бұрын
In some languages using switch statements can help make sure you've covered all cases of an enum, which is nice. It'll also usually error if you have duplicate values.
@Brad_Script
@Brad_Script 4 ай бұрын
it's the case with GCC, if you don't have a "default" block it will give a warning if you are missing a case for an enum
@snbv5real
@snbv5real 4 ай бұрын
Switch statement allows safe usage of enumerations with compiler errors and lints from not properly handling all cases, in addition, you're not allowed to have more than 128 if/else chains in MSVC, which is the minimum guaranteed for **C**,. Also not using switch statements because you don't like the way it looks means you shouldn't be using C++ at all if that's what you value, most things you should be doing are harder to do than the things you shouldn't be doing in C++, like C style casts vs static_cast, and you **really** don't want to be using C style casts unless you love heisenbugs and undefined behavior being a permanent fixture of your code.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
I use c style casts all the time lol and I don't have any problem with it. Also I never reached more than 128 ifs 😂
@dimanarinull9122
@dimanarinull9122 4 ай бұрын
The reasons I tell people to use a switch instead of if are: 1. Embedded/Legacy code, it IS running on old compiler as well, switch has a better chance of good optimization, but you would just explicitely code a LUT in those cases. 2. Multiple cases with the same code allowing for the elimination of duplicate code in the source file - less code = less bugs.
@sealsharp
@sealsharp 4 ай бұрын
Many years ago CPUs did execute code instruction by instruction and you got a nice fat printed book with a list how many cycles each instruction takes, so you could compare the speed by counting the assembler lines. Right now, you need to benchmark the actual code on real data that is in real positions in memory to get a real comparison because of the things a CPU can and will do. "Oh how bothersome!" If creating a representative benchmark is not worth the time you don't need the optimization.
@theairaccumulator7144
@theairaccumulator7144 4 ай бұрын
Also CPUs are so much more complex nowadays they can't even calculate exactly how long an instruction takes
@mytech6779
@mytech6779 3 ай бұрын
You can still get those books of instruction cycles and pipeline latency, just in PDF format. The calculation won't tell you the wall-clock performance because most operating systems are not at all realtime and any x86 after 386 is not realtime hardware even if you have an RT OS (and why 80386 was still manufactured in 2007 for industrial needs) and also memory bus and caching effects, branch prediction... BUT it will still give you the needed CPU cycles despite those cycles being out of order and interleaved with a bunch of other stuff. Still useful as a hints for making hyper optimisations targeted at specific CPU submodels, eg super computing, safety critical fully validated applications, and extreme low latency.
@hyde4004
@hyde4004 3 ай бұрын
Yea, even writing binary machine code doesn't get you "bare metal" control these days, let alone something like C or C++. A modern CPU is black fucking magic in and of itself, with layers upon layers of abstraction and optimization. It is nigh on impossible to make meaningful predictions, one has to measure real world situations.
@sinom
@sinom 3 ай бұрын
10:25 LLL is a C programmer. And as a C programmer he probably doesn't turn on optimizations since those will just "obfuscate the output"
@voodoo5191
@voodoo5191 4 ай бұрын
There is a point to be made about whether that performance gain from switch even matters (in C++ ofc it doesnt as much since it's mostly the same, but i'm talking about other languages). When people looked at yanderedev's code they often criticized the use of if's. And sure when we are talking about readability then that's a good case since it was just a bunch of nested dog shit. But performance wise it didn't matter and performance was usually the one thing that people talked about the most. Even in his terrible code, afaik the rendering was the main issue. Having said that. Great video :D
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yess, good point and good coment. the ifs werent the problem in his case lol wtf, it was the fact that he was using hudge unoptimized meshes for small objects and such. Also I don't really find it that bad to do an if chain. I like it actually 😂😭
@voodoo5191
@voodoo5191 4 ай бұрын
@@lowlevelgamedev9330 I'd say that if chain's aren't inherently bad. It's just there is a certain limit to them that if you cross it then it can significantly make your code more unreadable. But I have to say though, if's sometimes get too much hate.
@voodoo5191
@voodoo5191 4 ай бұрын
When it comes to yanderedevs code, The excessive nesting was the biggest issue for me. If an if chain doesn't have that much nesting it honestly can look pretty nice but in his case imo it was dogshit (But it also depends on what code of his we are examining).
@miroaja1951
@miroaja1951 4 ай бұрын
​@@lowlevelgamedev9330 the if's themselves weren't the problem as much as the need for them. Any 1000 line conditional is bound to be pretty slow if you have to run through even most of the checks. His issue wasn't that he was using if's instead of switches, instead it was way more about the horrible design of a monolithic character component
@notinla
@notinla 4 ай бұрын
Actually the rendering was dogshit as well, fps dropped insanely, and it was all because of bad design pattern (see details below) mostly regarding, you guessed it, a forest of ifs. As for why you might say that it wasn't his writing that gave the bad performance i suppose you got that information from himself, as he did a video on the bottleneck of his game. Plot twist, you shouldn't take biased advice from an one that performs awfully in his field, he didn't know how to debug properly and how the tools worked, so he saw "rendering bad" and said the engine doesn't do it (the rendering) well, while it actually didn't do it well because of what it had to go through to render, aka doing thousands of ifs per second (and honestly that's lowballing it). Now for the details regarding the design patters, instead of making a rendering and unrendering system for the npcs and giving each generic type of npc its own separate class with its own schedule etc, he just made a base class for Person and checked a ton of stuff to see how to update them (schedule, paths, personal characteristics). It was quite some time ago that i saw the the code, so i do not remember the very exact workings of it, but i do know how it went.
@templeofdelusion
@templeofdelusion 4 ай бұрын
9:10 "Fortunately, the difference was always very small" Lmao, 10% performance improvement with more readable code is MASSIVE, you get it for free, stop coping, switch is always better, the only reason to use if is if is more readable, which it often isn't. This state of things means that in 99% of cases, if is used as an error checking statement and not much more, because any complex enough problem will have enough cases that if becomes impossible to express properly.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
10% of a very small thing :))) I personally don't like switches but that is not the point. 10% of a small thing is so small that you can bearly measure it
@balijosu
@balijosu 4 ай бұрын
​@lowlevelgamedev9330 That misses the point. If profiling finds a bottleneck, 10% can be meaningful. That bottleneck can easily be switch/if logic.
@lowlevelgamedev9330
@lowlevelgamedev9330 3 ай бұрын
@@balijosu also one more thing, the case for that 10% difference was in a case where the if used a < comparison, something you can't even do in a switch.... If you write the if with only cases aka it is the same thing as a switch, it will be optimized 100% the same as a switch
@Vdevelasko
@Vdevelasko 4 ай бұрын
Readability aside, I think it's better to be skeptical by default. As a wise programmer once said "I don't trust constants anymore". Compilers can be extremely smart but they aren't AGI applied to code or anything similar. I think it's better to do whatever is more readable and then optimize as most people do. Good to know tho.
@cryonisc
@cryonisc 4 ай бұрын
I also think, which is very important, is that you can set warning or error flags if you miss individual switch cases. Lets say you ALWAYS want to loop over an enum (class), a bunch of if-statements won't trigger that warning, but a switch condition will.
@TheMaither
@TheMaither 4 ай бұрын
if < switch < if constexpr
@sledgex9
@sledgex9 4 ай бұрын
"if constexpr" is its own category. It's like a glorified "ifdef". (I don't mean it in a bad way)
@cristiandecu
@cristiandecu 4 ай бұрын
@@sledgex9 Constant expressions are nowhere near preprocessor stuff. Preprocessor directives are a way of pruning chunks of code while constexpr are basically executed at compile time.
@sledgex9
@sledgex9 4 ай бұрын
@@cristiandecu "if constexpr" is different than simple "constexpr". It (if constexpr) prunes code too.
@Jarikraider
@Jarikraider 3 ай бұрын
I pretty much only use switch statements when I'm feeling all fancy.
@yukizensho6603
@yukizensho6603 3 ай бұрын
switch statements are easier to read in some cases
@robstamm60
@robstamm60 3 ай бұрын
As always depends on architecture, compiler and compiler flags. On an early non optimizing C compiler for a single core non pipelining processor a chain of if clauses should end up as a chain of branch instructions and a switch should result in a jump to a jump table - so 2 branch instructions. Now with a modern optimizing C++ compiler it will produce machine code that merely produces the same output as the code you feed it. If you run this on a modern pipelining processor with branch prediction and speculative execution all bets are off to predicting if a manual optimization actually has any impact.
@ramoncf7
@ramoncf7 4 ай бұрын
Great video! Compilers are indeed very smart, but sometimes too smart, I recently stumbled across a bug in my code which didn't appear in debug mode, I was using a function address as a key in a map, which worked perfectly in debug, but in release the compiler optimized the code and reused functions (some from different libraries), and it broke everything because different functions which produced the same assembly were treated as the same function 😢 once compiled: never use function addresses to index (lesson learned I guess).
@TheJGAdams
@TheJGAdams 4 ай бұрын
I always use optimization and never debug. It's a way to discover bug as you are making it instead of later where you forget about it and now have no clue where it comes from.
@somenameidk5278
@somenameidk5278 4 ай бұрын
​@@TheJGAdamsi'm a little confused, you can have debug info on when compiling with optimizations?
@somenameidk5278
@somenameidk5278 4 ай бұрын
I tried to look up whether different functions are required to have unique adresses but all i found was a bunch of people arguing about it on StackOverflow. Apparently MSVC says no but Clang and GCC say yes.
@TheJGAdams
@TheJGAdams 4 ай бұрын
@@somenameidk5278 No, not debug info. There are other ways to find bug, I never used debug. Just try removing code, print messages, ect... It's just my way of doing thing.
@somenameidk5278
@somenameidk5278 4 ай бұрын
@@TheJGAdams i hate that workflow (having to wait for a 30 second loading screen every time i want to add some print() to my Don't Starve Together mod sucks, i would be pissed if i had to do that with a large project that takes minutes to compile) but whatever works for you i guess
@edgarkhachatryan9992
@edgarkhachatryan9992 4 ай бұрын
Thank you for this video. I really waited for someone to post a video about this topic, because a lot of people are confused about it. Please make more videos about compiler optimizations/technics and static analysis. This topic is very interesting, because you learn how compiled languages work under the hood
@DLCSpider
@DLCSpider 4 ай бұрын
C# Godbolt results: (Integer comparisons, numbers chosen randomly) Short chains: generated assembly is different but as far as I can tell roughly the same strategy, which is just a linear search. Can't tell which one is faster from just the assembly but shouldn't matter too much. Long chains (>20(?)): if statement stays the same but switch turns into a binary search, which should actually be faster, assuming Bonus ternary: since NET 8 the ternary operator tries to use conditional moves and for short chains it does; long chains become regular if statements but (again) with slightly different code generation.
@1ups_15
@1ups_15 4 ай бұрын
This is good to know, however I think we should still use switch statements when relevent; it's always great to explicitly write what you want your program to exactly do, rather than letting the compiler do it for you
@oskar_schramm
@oskar_schramm 4 ай бұрын
Amazing video! You know what is even faster and branchless, atleast with Shader code -> using lerp as an if statement ;)
@ivlis.w
@ivlis.w 4 ай бұрын
Yanderedev was right.. 💀
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
well no because he was using c# so I don't think it applies to him. Skill kssue because I use C++ and I can write if chains with no problem
@ivlis.w
@ivlis.w 4 ай бұрын
​@@lowlevelgamedev9330 fair, even still it probably was before the recent release that introduced the optimization So I guess he was just ahead of it's time (? 😹 Maybe some day C# does this too
@fkeyzuwu
@fkeyzuwu 4 ай бұрын
​@@lowlevelgamedev9330 from what i remember, c# also optimizes from around a certain number of if statements into a switch statement
@timmygilbert4102
@timmygilbert4102 4 ай бұрын
​@@lowlevelgamedev9330unity transpile c# IL into c++ with IL to CPP, specifically to squeeze performance from the c#. Which mean it's equivalent to coding in c++. From the era before Riccitello and unity were making innovation that mattered.
@TheLucidDreamer12
@TheLucidDreamer12 4 ай бұрын
C# has to be interpreted into an intermediate language before that is compiled to machine code. This adds significant overhead because the if statements in the intermediate language may not have the nice properties needed for compiler optimizations. Those if statements are likely hogging the memory bus and branch predictor, leading to the infamously bad performance.
@Zullfix
@Zullfix 4 ай бұрын
4:38 I expected the C# JIT assembly of switch and if-else to be identical, however there is actually a bit of difference. The switch assembly is slightly shorter than the if-else chain, however the if-else chain uses some SIMD vmovdqu instructions whereas the switch used just mov. Tested with sequential integers.
@Zullfix
@Zullfix 4 ай бұрын
Also tested on sharplab. There was a difference in the generated assembly between sharplab and godbolt, so I chose to trust sharplab. Edit: I was accidentally looking at debug assembly. The release assembly is a lot closer and lacks the SIMD mov.
@Zullfix
@Zullfix 4 ай бұрын
I think the biggest reason for the difference in the assembly is because the compiler optimized the switch into a jump table in the IL, meanwhile the if-else chain remained as a series of jumps at IL compile time, giving the JIT two very different scenarios to work with.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yoo thanks for testing it and letting me know, so it seems like in c# switch is faster
@Zullfix
@Zullfix 4 ай бұрын
Important note: I was looking at the debug assembly like an idiot. The release assembly between the two scenarios is still different, but a lot less so. i.e. the SIMD mov instructions are gone.
@Zullfix
@Zullfix 4 ай бұрын
​@@lowlevelgamedev9330I didn't write any tests because its 3am, but based on the assembly switch should indeed be faster (when the values can be converted to a jump table at compile time)
@harald4game
@harald4game 3 ай бұрын
Switch IMO improves readability a lot. For multiple ifs one has to check if ifs the same value if, if it's equals or something else and you have very short lines. So it's a lot easier to understand what's going on.
@Kiyuja
@Kiyuja 4 ай бұрын
I can barely speak about low level compiled stuff because my only language in that field is Rust and I dont know too much about LLVM to make a case. BUT I can tell you that in higher level languages like C# the if-else blocks will automatically be compiled to a switch or boolean expression. The compiler already does this, even on the IR. I personally like switch statements, because they look tidy, but to really see a difference you usually have to run things for so many iterations that it mostly doesnt matter, pick the one you like...
@StrielokPLsz
@StrielokPLsz 4 ай бұрын
in embedded world you have a ton of proprietary compilers with code obsolete beyond all recognition or with paid optimizations like XC8 from microchip
3 ай бұрын
Dispatch is a bit more subtle than picking a language construct. In a tight loop, consider branchless state machines to avoid code pointer offset changing. Useful for lexing and possibly bytecode interpretation.
@Jakobg1215
@Jakobg1215 4 ай бұрын
For rust I use the match statement lot more than if statement mostly due to it looks nicer with enums.
@SMorales851
@SMorales851 4 ай бұрын
Not only does it look nocer, it is much more powerful, mainly because of the destructuring
@xphreakyphilx
@xphreakyphilx 4 ай бұрын
You can get the destructuring with if let statements, but match statements are definitely way nicer to read and write
@wertigon
@wertigon 3 ай бұрын
It is crazy how good compiler opt has gotten 🙂 I will still use a switch for state machines though, ever since I discovered the switch (state) followed by case STATE_A: state = stateA(); break; pattern norhing even comes close for readability.
@_M_643
@_M_643 3 ай бұрын
I think generally it's still good practice to write switch statements where possible. They also look pretty clean.
@Julienraptor01
@Julienraptor01 4 ай бұрын
tbh i quite disagree and would take a switch to an if else chain nearly each time Because when i see a switch, i alr OK, there's gonna be multiple code paths here Whereas when i see an if, i don't always know if there's gonna be an else after Also the switch has this neat thing of telling you "here we will have multiple code paths based on the same input" where an if else chain could actually have different inputs for the code paths So one isn't better than the other, it depends on the context
@Juss_Chillin
@Juss_Chillin 4 ай бұрын
Thank you for finally ending this long lasting discussion! Great video
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
glad you liked it bro 💪💪 someone had to do it
@DeathSugar
@DeathSugar 4 ай бұрын
At times when I've tested it (somewhere between 2013 and 2015) gcc didn't had the optimization to lookup tables, but clang had. Also randomized values in cases/ifs is kinda corner case which rarely introduced in real code and if it happened to be the case it bound to be slow anyway regardless of what you choose. We didn't supported windows, so I didn't checked if MSVC also did it as well, but most likely they also didn't. So, short answer - switches are still more faster, readable and less error prone then ifs if you have llvm backend. Other corner case - not everyone use O3 opt level due to fucky-wacky compilers do during hardcore optimizations - also room for speculation. If I remember correctly simple cases optimized in clang's O2 as well, but GCC might not adopted this behavior.
@jannegrey
@jannegrey 3 ай бұрын
My initial thought was that compiler makes them similarly in the end or even that they are equivalent. Not that I know that much about coding or compilers. I used to code a bit over 20 years ago and I watch your videos from time to time. EDIT: So I watched the video and it seems I was in the ballpark. Personally I mostly wrote quite simple code and to me switch was more readable and easier to use when there would be more than 3 cases. Not that it mattered for the code I was writing since it still took milliseconds to execute ;)
@dahahaka
@dahahaka 3 ай бұрын
C#/Net definetly compiles switch statements to if else chains unless you have a huge number of cases :)
@andreitgk4748
@andreitgk4748 4 ай бұрын
it's not faster by itself but having a cleaner code helps.Usually if statements like switch are both slower when you could've used an equation.
@insentia8424
@insentia8424 4 ай бұрын
I use switch statements for state machine update functions (in C). Fragmenting that code into smaller functions that are scattered around with unnecessary empty space between them imo makes the code only more cumbersome to read and harder to understand. I don't remember using them for anything else, now that I think about it.
@atackhelikopter4303
@atackhelikopter4303 4 ай бұрын
big problem with this is that sometimes compiler optimizations can introduce bugs (i don't know how safe O3 and O2 for example are in modern compilers, but there might be this risk), so sometimes you would prefer to not use them, and so switch can be faster
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
um I have never heared about that, I don't think you can ship a big project without optimozations. It just won't run at more than 1 fps
@atackhelikopter4303
@atackhelikopter4303 4 ай бұрын
@@lowlevelgamedev9330 not really best coding practices can secure like 4x slower than o3 optimized, plus you can optimize some parts where it doesn't matter that much if it were optimized or not to make it like 2x slower, but sometimes in a project the cpu speed might not be the problem and it's just the GPU, so some games might not have optimizations turned on (at least for the release version)
@atackhelikopter4303
@atackhelikopter4303 4 ай бұрын
oh yeah, sometimes you don't even have to necesseraly optimize your code if you use data structures, if you use for example an unordered map, most of the optimization is implemented in the class itself, so you can get away not turning optimizations for that part of the code
@uxel-g9y
@uxel-g9y 4 ай бұрын
I have personally done something like this for java 8. However only for swiching vs ifs on strings of about 10-20 characters in length. The answer was that if statements are faster for less than 7 comparisons. Switch statement wins for 7 to 30 branches. After 30 branches the HashMap (precomupted into a static variable) wins. Note tho that my use case was doing a trivial mapping from String -> Some Result. If you need to run code then I would not be sure that the HashMap wins that early. Really really large switch statements become so slow however that i am certain that at some point you will be faster with putting Consumer/Function/Runnables instances into a HashMap. I have tested this with -Xcomp setting. So the JIT "may" magically optimize this in a way that -Xcomp did not to skew these results. I have no idea if any of this still holds true for anything that is not java 8. Probably not.
@Xankill3r
@Xankill3r 4 ай бұрын
Complicated switch statements in C# are often much faster than equivalent if statements - at least as far as the IL code is concerned. I haven't looked at what the modern runtime does in terms of JITting it all. Basically the C# compiler does really smart stuff with switches on strings and numerical values where it will basically convert them into a convoluted looking multiply nested group of ifs. For instance in the case of numerical values the compiler may figure out that all the possible cases are split equally above and below some value X. It will convert that switch into a single pair of outer If/Else along the lines of = if (input < X) .... else .... Long story short the C# compiler does some really smart shit with switches in order to minimize the number of comparisons on the average invocation.
@brianb2308
@brianb2308 4 ай бұрын
For enums I like to avoid the default case because then if I add another enumerator to the enum I get a warning for not handling it everywhere that we run different code or get different values for the different enumerators
@AURORAFIELDS
@AURORAFIELDS 4 ай бұрын
there's cases where you have an if chain (as opposed to if/else chain) that also has side-effects within the block or the condition test. Similarly if you allow control flow to fall through switch cases it can have side effects. those can wreck havok for the compiler optimizations. switch and if chains are never equivalent as far as optimizations are concerned. but there's a lot of very simple cases where they can be treated practically identically anyway. There's always an argument to be made with C++ in theory supporting so many architectures that if you plan to "optimize code" you really ought to understand the platform you're working with before diving into micro-optimizations (that probably don't matter anyway) such as switch vs if. in theory switch is always faster, it's *designed* to be faster. in practice compilers are really smart. but there's a possible argument to be made with compiling times. but with C++ you're probably looking at first to have as little templating as possible anyway for that.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
if the if chain looks identical you can have the same side effects and stuff. A friend of mine looked at clangs llvm code and the if statement is turned into a switch and than it is worked on in the same way as the switch. ``` /// 4, 8, etc. Note - LLVM converts the if-then-sequence to a switch /// instruction in SimplifyCFG.cpp. Then, the backend decides how code for /// the switch instruction is generated. ```
@flameofthephoenix8395
@flameofthephoenix8395 4 ай бұрын
I haven't ever actually used a switch statement, however, there is an easily seeable benefit to the switch statement, while it will run at the same speed at run time, the compile time will be slower if you rely on an if statement tree because the compiler has to recognize this which means that while they've made things faster for beginner developers who don't optimize well they have as a result caused compiler time to be slower for everyone, so now the if statements in general are ideal to avoid if you want fast compile time. A compiler should not try to optimize poor code as this means there are extra unnecessary checks being done at compile time even for performant code.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
not really. This is probably the last thing that is slow in a compile time. The slowest thing is linking, than things like a ton of template code
@flameofthephoenix8395
@flameofthephoenix8395 4 ай бұрын
@@lowlevelgamedev9330 Granted, but I guarantee that if they removed every compiler feature except for the things that are actually required it would compile faster, and likely by a significant margin.
@nahmanbop9248
@nahmanbop9248 4 ай бұрын
I think the take away point is that ifs are slower than switches however the compiler can optimize the if into a switch so you are probably fine. When I have massive logic I prefer to use state machines instead of ifs anyways.
@andersr9545
@andersr9545 4 ай бұрын
could you elaborate on what you mean by the last statement about state machines vs ifs?
@p0t4toePotato
@p0t4toePotato 4 ай бұрын
instead of creating complicated easy to break nested conditionals with boolean operations, you rethink your design to separate it into states and events, the definition of the states makes your code cleaner because each state implicitly represents your complicated conditionals, then, the events which can cause a state transition are clearer and easier to understand and document
@Brad_Script
@Brad_Script 4 ай бұрын
switch can actually be optimized into an if/else statement when the number of cases are very low
@SianaGearz
@SianaGearz 4 ай бұрын
Switch statement will not always become a jump table, it can also under circumstances become a binary search sequenced comparisons. Anyway optimising instructions is usually of very limited utility when targeting out-of-order CPUs, there are maybe one or two places in the program where you might want to do this. The main optimisation focus should be on memory access, since in the time to open a page of RAM, a lot of arithmetic could have been performed, so if you don't care about memory accesses, your program will just be diffusely slow everywhere as it overtaxes the caches and it's more difficult to introduce these type of optimisations at a late stage of development than micro-optimisations.
@sonphisica3136
@sonphisica3136 3 ай бұрын
You've used rand() inside benchmark body, if I am not mistaken, which is not perfect. I think, it could have taken a lot more time then switch/ if itself. But you've showen assembly so it's all good.
@lowlevelgamedev9330
@lowlevelgamedev9330 3 ай бұрын
rand is kinda cheaply implemented it is just a few operations so it is good
@wicked_sash
@wicked_sash 4 ай бұрын
If is slower unless it is optimizef, just depends on how much you trust the compiler. I dont trust it that much and try to take every optimization i can. But you got vslid points ngl.
@severgun
@severgun 4 ай бұрын
9:16 10% is HUGE difference.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
if that is not a critical code path no
@alihene2225
@alihene2225 4 ай бұрын
Switch is definitely useful in embedded or osdev where optimizations can sometimes (rarely though) have negative effects
@Brad_Script
@Brad_Script 4 ай бұрын
the only reason people hate switch is the mandatory "break"
@Oler-yx7xj
@Oler-yx7xj 4 ай бұрын
Oh, I only just understood, that `case: FOO` syntax is supposed to be a label, that's why you don't need braces variables are not scoped and it falls through
@harryvpn1462
@harryvpn1462 4 ай бұрын
The yandere dev era was the worst to be a programmer because you had ppl who have never coded lecture you in the use of if statements
@templeofdelusion
@templeofdelusion 4 ай бұрын
those people didn't make a game with 0 features that runs below 60fps on modern hardware...
@Brad_Script
@Brad_Script 4 ай бұрын
yandere dev is the worst because he literally put the logic of the whole game in a single file, also a lot of the if/elses he wrote go away with classes/inheritance.
@Greeem
@Greeem 4 ай бұрын
@@templeofdelusion and specifically targeted at freaks too lol
@milasudril
@milasudril 4 ай бұрын
Maybe you can break the optimizer by calling a function with a reference to the variable that you intend to switch on. Aliasing disables a lot of optimizations.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yo I will check that, tho I don't think it would since once tou get inside the branch that variable wont affect the code after, but it is worth checking
@joemama-j8b
@joemama-j8b 4 ай бұрын
The switch and if discussion is just a Venn diagram, there are cases where they are both able to do the same thing, the same way, and others where one option is preferred over the other. I would rather have simple assert style if statement, to return early in a function, over a switch, and a switch structure, to make a function more legible, over a more, visually, complicated if statement. Even if somebody makes the "wrong" decision it won't impact the code nearly as much as design flaws.
@the-pink-hacker
@the-pink-hacker 3 ай бұрын
My take is that in a compiled language for x86 there is no point to micro optimizations unless you really know what you're doing. The only time I've ever decided to write assembly was for EZ80 an obscure 24-bit microprocessor used in TI-84+ CE calculators. I felt that there was no way LLVM could produce better results than me taking the time to learn the architecture. But for x86 or ARM, there is no way in hell I could do better.
@MichelHermier
@MichelHermier 4 ай бұрын
Unless I'm mistaken, you only covered the simple switch/if cases. The switch syntax is sometimes very messy were variables can be scoped in a block, within the switch, sharing access through multiple cases, mixed with fall-throught... making switch a glorified goto. While I agree the simple cases are optimized to near equality, I wonder if that stay true with these "dirtier" usage. I don't mean someone have to use them, but sometimes it is "simpler" to write them that way. It can make the code surface way smaller, readable, and probably more optimized by expressiveness, then their equivalent in if code.
@peppidesu
@peppidesu 3 ай бұрын
never underestimate your compiler, folks
@lensy6
@lensy6 4 ай бұрын
This is more of an issue that people repeat things they hear without knowing the specifics of why something was said. It is true that in certain circumstances such as using certain compilers for certain languages in certain contexts a switch statement is faster than an if statement, all it takes is someone hearing that a compiler is faster without understanding why it only applies in that scenario and repeating it and then other people who don't know the context will also repeat it and so on. This isn't just a programming issue, it occurs in all fields such as any time someone mentions the holy roman empire someone will repeat the quote "neither holy nor roman nor an empire" even if someone is talking about something like the crowning of otto i and not the late empire of the quote's origin when the hre was a very different beast.
@dungeon4971
@dungeon4971 4 ай бұрын
I looked at the title and thought to myself so switch statements are faster than if statements in c
@anon_y_mousse
@anon_y_mousse 4 ай бұрын
Well, first of all, I'm still on gcc 10.3.1, so large if-chains won't be optimized in that way necessarily. I'd wager many more people are likewise on older compilers that optimize switches better than ifs. However, switches are not only easier to read and more understandable as to intent, but with regard to enums you can turn on warnings that allow you to ensure you're checking every valid case. Of course, I'm not one of those people that considers the compiler smarter than the programmer, but that's because I know I'm smarter than the compiler in most cases. It probably helps that I still do assembly programming from time to time and that I've written multiple compilers, but whatever. Also, both C# and Java get compiled before being run and that allows for optimizations, but more than that, both can perform additional optimizations at runtime which can affect the speed of a long-running application. That's not to suggest that they're good languages, because they both suck, but they can potentially optimize more than other languages if the VM is tuned right. That said, C# mostly gets compiled to a native binary these days and won't necessarily allow for that level of optimization.
@brynnerjayantiquesa7441
@brynnerjayantiquesa7441 4 ай бұрын
Well in low level learning video, you might have overlooked the optimization level like -o2 in argument in gcc
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
than idk what happened, I have tested his code with a c compiler and with a cpp compiler. Maybe he had an old compiler than
@jagd_official
@jagd_official 4 ай бұрын
I find the switch statement an eye sore for my eyes. Code needs to be beautiful to the eyes, artistic indeed
@yiranmushroom
@yiranmushroom 4 ай бұрын
For things like this, you should not rely on compiler's optimisation, Except for Return Value Optimisation. I don't think others are guaranteed. If there is a case which performance is very important. Use switch.
@nangld
@nangld 4 ай бұрын
Is your test suite public, and can determine if the random compiler optimizes the ifs properly? Also, GCC and Clang allow computed jumps by taking the label addresses.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
you can find most of my tests in the description. I checked them by hand by looking at the asembley and comparing the speed
@tutacat
@tutacat 2 ай бұрын
It doesn't matter for longer cases, because if your expressions are that many, your coupling is too high, you need to break it down.
@Brad_Script
@Brad_Script 4 ай бұрын
I still think you should use switch with enums, the compiler can detect if you didn't handle all cases.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yo I am not against switch, just think its silly to say that just by using switch your code will be much faster
@HinaraT
@HinaraT 4 ай бұрын
Remember that your examples only show switch statement without any fallthrough behaviour !! Which might not be as straight forward to write with if statement Also as you told before you assume everybody is using compiler optimization which is not always the case especially while debugging (even if it is a bad idea as compiler optimization might introduce bugs due to undefined behaviour)
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
I showed the fallthrough, that one is faster on the switch. Also don't saying compiler optimization is a bad idea, Software is always shipped with optimizations on
@HinaraT
@HinaraT 4 ай бұрын
@@lowlevelgamedev9330 it was debugging without optimizer option which is a bad idea as code might not be the same and might have different bug while optimized which you could not have caught without the optimizer flags
@HinaraT
@HinaraT 4 ай бұрын
@@lowlevelgamedev9330 "I showed the fallthrough" Timestamp please ?? case1: case2: doSomething() break; Is not fallthrough by fallthrough I mean a case falling in another case after having executed some instructions, which is also really hard to express with if statement as you need to reverse the whole logic " Also don't saying compiler optimization is a bad idea" I didn't said that I said to always debug in the same environment with the same optimizer flags while debugging as optimization might change the behaviour of your code if you let some undefined behaviour in it.
@theevilcottonball
@theevilcottonball 4 ай бұрын
Compiler are sometimes smart, but sometimes they are extremely dumb. For example the compiler failed to SIMD vectorize many of my loops, then I thought that vectorising the loop would mean a differently rounded float result so it could not, I wrote intrinsics anyway....
@Alexi_Blue
@Alexi_Blue 3 ай бұрын
I love the Aria Math while explaining the Gauss sum lol
@lowlevelgamedev9330
@lowlevelgamedev9330 3 ай бұрын
best part of the video
@ThaitopYT
@ThaitopYT 4 ай бұрын
*Always benchmark* if you serious about performance. It doesn't matter if your switch statement -2ms faster if your game take 10 minutes just to load a single photo-realistic toothbrush that has millions polygon.
@taylorallred6208
@taylorallred6208 4 ай бұрын
It’s so ironic that C++ tend to think more about optimization while the compiler does so much more for them than other languages. Meanwhile, JS and Python devs can easily slow down their code by 100x without thinking about it. C++ actually let’s you write simple and readable code without having to worry about performance the vast majority of the time.
@Spartan322
@Spartan322 4 ай бұрын
C++ copies data by default, this is extremely slow behavior.
@iWillRun_K
@iWillRun_K 4 ай бұрын
python/JS target use are quite different than c++
@tzimmermann
@tzimmermann 4 ай бұрын
@@Spartan322 It's a bit like using one word for another in a conversation, and complaining that the other person does not understand what you meant to say. There is no such thing as "copy by default" in C++. You're responsible to use the appropriate syntax to pass things by value or by reference, depending on what you actually need to happen. Also... Heard about copy elision? More often than not, when the syntax suggests a copy, there is no copy at all. And modern compilers will even optimize out your fixed-size memcpy calls. Still, memcpy is already fast as hell.
@Spartan322
@Spartan322 4 ай бұрын
@@tzimmermann Copy elision only works on returning a singular stack allocated object, it needs to be a value allocated on the stack, and it doesn't work if you return different values on the stack conditionally, in such case it will call the copy constructor, (no compiler can resolve copy elision for that because the compiler cannot know which to return) if you push a value into a function the behavior it will perform is a copy, (unless it has a deleted copy constructor, then its a syntax error) go ahead and try this with std::string or std::vector, see what happens, (hint: it will copy the data and allocate new copied data so long as it can be copied) if you actually track the copy constructor and allocations you'll see a copy every time you call a function argument. All classes call copy constructors, many other languages don't inherently perform copy by default, its a behavior legacy related to its C derivation. Go look up copy elision on cppref, it will tell you exactly what I said. Java, JS, C#, D all do assign by reference as the default for class types, Rust by default moves class types, as does Zig. (generally) Copy by default is the slowest and that's why in most other languages the choice for the default behavior is not to perform a copy. (the only case where reference is more expensive is with primitive types smaller then the pointer size, which most primitives actually don't, least in C++, for 64 bit platforms that's usually an 8 byte, or 64 bit, object, you could make a struct that small but that's almost never the case)
@Spartan322
@Spartan322 4 ай бұрын
@@tzimmermann Copy elision only works on returning a singular stack allocated object, it needs to be a value allocated on the stack, and it doesn't work if you return different values on the stack conditionally, in such case it will call the copy constructor, (no compiler can resolve copy elision for that because the compiler cannot know which to return) if you push a value into a function the behavior it will perform is a copy, (unless it has a deleted copy constructor, then its a syntax error) go ahead and try this with std::string or std::vector, see what happens, (hint: it will copy the data and allocate new copied data so long as it can be copied) if you actually track the copy constructor and allocations you'll see a copy every time you call a function argument. All classes call copy constructors, many other languages don't inherently perform copy by default, its a behavior legacy related to its C derivation. Go look up copy elision on cppref, it will tell you exactly what I said. Java, JS, C#, D all do assign by reference as the default for class types, Rust by default moves class types, as does Zig. (generally) Copy by default is the slowest and that's why in most other languages the choice for the default behavior is not to perform a copy. (the only case where reference is more expensive is with primitive types smaller then the pointer size, which most primitives actually don't, least in C++, for 64 bit platforms that's usually an 8 byte, or 64 bit, object, you could make a struct that small but that's almost never the case)
@u9vata
@u9vata 4 ай бұрын
This is actually really bad... The reason is at 7:58... I prefer the optimizer not auto-decide this but to let me decide when I want the jump table and when I want ifs.... because sometimes ifs are faster because of branch prediction. So its bad they changed this to be honest...
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
I don't know what to say. That case will probably not happen in practice. Its better like it is for the most part.
@u9vata
@u9vata 4 ай бұрын
@@lowlevelgamedev9330 Oh it is not at atl improbable that branch predictor outperforms jump table. It all depends on the distribution of the values. It would be interesting to see if the compiler also do this jump-table optimization if you mark some of the if statements with if(__builtin_expect((condition),1)) Because I expect that it should totally break the optimization into a regular if when that gets added - hopefully at least... I mean if they automize this, that I would totally consider a bug., because not all CPUs have jump target prediction and some state machines are very hard distributed on simple cases. I actually prefer languages where its semantics that define which happens under the hood so its not surprising if its a jump table or not but I guess all one has to do is to add LIKELY macros to handle this if you want to properly hand-optimize...
@okta25
@okta25 4 ай бұрын
Ma uit la tine de cateva luni, si acum imi dau seama ca esti roman 😂
@vast634
@vast634 4 ай бұрын
You performance problems likely will not stem from using if instead of switch anyways. There is usually easier apples to pick to improve performance.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
yess that's my point 💪
@110SEBA15
@110SEBA15 4 ай бұрын
I'm just here to say that I heard the Minecraft music immediately and assumed I had Minecraft open. 😂
@nordgaren2358
@nordgaren2358 4 ай бұрын
Relying on the compiler to optimize your if statement when it should be a switch statement, is asking for trouble.
@JosephBlade.
@JosephBlade. 3 ай бұрын
I think if is better because you can generally guess mostly statified condition and place other stuff in else 😂 I didn't test this but it would work I suppose
@SpiraSpiraSpira
@SpiraSpiraSpira 3 ай бұрын
one would think that the compiler would obviously optimise something as simple as a switch or nested if statement to the fastest version by itself. this isn't the 1980s
@deadlyorchard
@deadlyorchard 4 ай бұрын
The preprocessor removes white space like empty lines and indents. 9:24 it would make no sense for blank lines to cause different compiler outputs. Honestly, you would’ve been better to focus on how smart the compilers have become over the years, rather than a clickbaity title about performance metrics.
@vulnoryx
@vulnoryx 4 ай бұрын
I will never be as smart as those people that made the compilers
@aldi_nh
@aldi_nh 4 ай бұрын
you didnt account for the time it takes for compiler to optimize the code. i imagine a big project would take a long time to compile, optimization will arguably gonna make it worse. i mean, wouldn't it be silly if you want to add a single feature to said project but since you use that "if else" instead of "switch case", everytime you want to debug it, you either - compile with optimization, takes longer time to compile, run the same as switch case, or - compile without optimization, quicker compilation, but run slower than switch case it would be easier and better to just use switch case right away, compile without optimization for quick debug, then optimize later when the project is ready for production
@farukyldrm8498
@farukyldrm8498 4 ай бұрын
from the title, i misunderstood that it is just the case for c++ and in c swich is still fast. and ı got angry. now ı am okay. esp. after hearing someone saying "compiler better at optimization than you"
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
well cpp and other compiled languages yes
@elias-ou2sp
@elias-ou2sp 4 ай бұрын
"switch is not faster than if" everything wrong with programming in a nutshell
@Brad_Script
@Brad_Script 4 ай бұрын
the title is clickbait, switch is in fact faster than if he even admits it in the video lol. The compiler replaces ifs with switch to make the code faster.
@severgun
@severgun 4 ай бұрын
Almost never value to compare with branches known at comp time. So there is no optimisation possible that will jump to correct branch without comparison.
@barneybarney3982
@barneybarney3982 4 ай бұрын
on pc it really doesn't matter, even if the difference will be like 200% it will most likely translate to a few nanoseconds. for simple comparisons i use a switch because it looks more readable to me.
@balijosu
@balijosu 4 ай бұрын
A few nanoseconds can matter if you're calling the function a lot.
@barneybarney3982
@barneybarney3982 4 ай бұрын
@@balijosu sure, but most of the time it still means that it will be slower by one minute each year. and in that case there is just no point in optimalisation, if it saves so little time, readability(not for today you, but for you after 5y or anyone that will be using this code) is way more important. don't get me wrong, in some edge cases it's really worth it to save 0.01% of the time and throw readability out of the window, but for the vast majority cases +200% time but easier readability is a better way to go.
@flameofthephoenix8395
@flameofthephoenix8395 4 ай бұрын
2:46 Unfortunately, true, but the compilers getting smarter has hardly anything to do with that. It is mainly because the vast majority of our supposed "programmers" are actually just artists using other peoples' pre-made engines.
@dovos8572
@dovos8572 4 ай бұрын
i wonder if we get a different result if we have if else if and else for the chain. will it still create the jump table or not? oh wait you did the ifs as else ifs. so the question should be what happens if we remove the else a the end of the lines.
@ani_sci
@ani_sci 4 ай бұрын
"If" is faster then "for" up to 100 times, you can test it. With only "if " and "goto" you can make "for","while","do while" loops easily.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
I find this very hard to believe bit this makes it more intreging, can you send me on my discord an example?
@ani_sci
@ani_sci 4 ай бұрын
@@lowlevelgamedev9330 My bad - up to 10 times kzbin.info/www/bejne/eWnQcomqp6ZlqJI
@Brad_Script
@Brad_Script 4 ай бұрын
but that doesn't make sense, aren't loops compiled down to conditional jumps anyway ?
@ani_sci
@ani_sci 4 ай бұрын
@@Brad_Script Yes they are. If you look at assembly after compilation - there are loops made of jumps and labels ))) Programming languages are made to READ CODE by humans. And all these strange things as "
@kubolor1234
@kubolor1234 4 ай бұрын
As someone with ADHD I prefer switch statements
@Nanagos
@Nanagos 4 ай бұрын
In Java, switch statements are faster, because they are read as jump tables by the interpreter (At least the old ones). The default Java compiler doesn't optimize if statements, because it is in Java's philosophy, to keep the bytecode close to the source code.
@rrutter81
@rrutter81 4 ай бұрын
i like this video, but all it did was make me want to write switch statements. In no case was if faster, yet in multiple cases switch was. To be fair, i agree that readability is more important than some silly optimization no one will notice.
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
um I won't really say in multiple cases switch was :)) It took me a few days and help from people to find the cases where switch is and also the cases where it really is a difference trust me you would never write them in your life 😂
@olbluelips
@olbluelips 4 ай бұрын
Thank you. This is one the most annoying things to constantly read. There’s more nuance to it than just “switch is better”. Also C++ compiler knows Gauss? Beautiful lol
@xardinlume7345
@xardinlume7345 4 ай бұрын
I like the extensive testing and the honesty, but if you start to wonder if an 80 cases if or switch is faster, you probably should wonder if your code is properly designed first lol Also most of the time the bottleneck of performance will be found ij big algorithms/rendering, so I'm not sure if the debate is relevant Still thanks for the testing
@lowlevelgamedev9330
@lowlevelgamedev9330 4 ай бұрын
the debate is indeed not really relevant but I wanted to make a video because the claims that people mad made no sense to me
@xardinlume7345
@xardinlume7345 4 ай бұрын
Understandable lol
How I 2.81x my FPS, with a simple OpenGL trick!
3:31
Low Level Game Dev
Рет қаралды 26 М.
What I do to never have to worry about memory leaks!
8:03
Low Level Game Dev
Рет қаралды 47 М.
Tuna 🍣 ​⁠@patrickzeinali ​⁠@ChefRush
00:48
albert_cancook
Рет қаралды 148 МЛН
How Strong Is Tape?
00:24
Stokes Twins
Рет қаралды 96 МЛН
The Art of Linux CLIs
8:35
Mults
Рет қаралды 438 М.
My game is 262,000 times faster than Minecraft. I'll show you how.
12:20
IGoByLotsOfNames
Рет қаралды 1,3 МЛН
This is the Best Pointers Video there is 💪
20:48
Low Level Game Dev
Рет қаралды 16 М.
Python laid waste to my C++!
17:18
Sheafification of G
Рет қаралды 129 М.
I made a physics engine in C++!
8:21
Low Level Game Dev
Рет қаралды 10 М.
why are switch statements so HECKIN fast?
11:03
Low Level
Рет қаралды 434 М.
It's not hard to make games in C++
6:23
Low Level Game Dev
Рет қаралды 72 М.
i got laid off... so i made a game...
24:08
bewky
Рет қаралды 629 М.
Tuna 🍣 ​⁠@patrickzeinali ​⁠@ChefRush
00:48
albert_cancook
Рет қаралды 148 МЛН