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

Поделиться
HTML-код
  • Опубликовано: 24 окт 2024

Комментарии • 471

  • @cFyugThCzvAqYaGmxRgfCKTuvHMEjQ
    @cFyugThCzvAqYaGmxRgfCKTuvHMEjQ 2 месяца назад +142

    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  2 месяца назад +17

      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 2 месяца назад

      Not every language uses LLVM...

    • @johanngerell
      @johanngerell Месяц назад +1

      @cFyugThCzvAqYaGmxRgfCKTuvHMEjQ Then you should mention what he did that caused the unexpected result, because he *did* measure, right?

    • @Ether_Void
      @Ether_Void Месяц назад +8

      @@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 Месяц назад

      It is hard

  • @sledgex9
    @sledgex9 2 месяца назад +591

    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 2 месяца назад +37

      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 2 месяца назад +23

      Yeah, I can much easier parse the switch @ 7:51 than its matching if

    • @theevilcottonball
      @theevilcottonball 2 месяца назад +6

      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  2 месяца назад +45

      idk personal prefference. I like to type less

    • @LaynaStambaugh
      @LaynaStambaugh 2 месяца назад

      @@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 2 месяца назад +507

    So, yandere dev already knew to trust the compiler, he was ahead of his time.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад +130

      smartest programmer under the hood actually 😌

    • @Exvixcity
      @Exvixcity 2 месяца назад +80

      ​@@lowlevelgamedev9330 not smart enough to know the age of consent

    • @ITR
      @ITR 2 месяца назад +21

      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 2 месяца назад +23

      @@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 2 месяца назад +15

      He was programming in C# not C++

  • @LinguisticMirage
    @LinguisticMirage 2 месяца назад +380

    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  2 месяца назад +55

      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 2 месяца назад

      ​@@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 2 месяца назад +21

      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_ 2 месяца назад +12

      @@lowlevelgamedev9330 msvc optimization fails (you mentioned at 9:25) left the chat

    • @cyanmargh
      @cyanmargh 2 месяца назад

      @@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)

  • @SimGunther
    @SimGunther 2 месяца назад +120

    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 2 месяца назад +1

      Exactly!

    • @kodicraft
      @kodicraft 2 месяца назад +27

      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 2 месяца назад +11

      ​@@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 2 месяца назад +1

      ​@@MrDavibuwhy? You would never turn off optimization fot actual production code..

    • @yellingintothewind
      @yellingintothewind 2 месяца назад +6

      @@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.

  • @_emik
    @_emik 2 месяца назад +62

    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 2 месяца назад +1

      JIT for the win!
      Or maybe just RyuJIT, jvm sucks 💀

  • @otrqffaimajg
    @otrqffaimajg 2 месяца назад +81

    i need to trust him, he sounds like a Russian hacker.

    • @thebrowhodoesntlift9613
      @thebrowhodoesntlift9613 2 месяца назад +9

      That accent doesn't sound Russian, maybe Italian? South American?

    • @eetukuru787
      @eetukuru787 2 месяца назад +20

      @@thebrowhodoesntlift9613 Romanian.

    • @RoopsForge
      @RoopsForge 2 месяца назад +24

      He is from the city of Rome, Romania, United States of Russia.

    • @ThatTanishqTak
      @ThatTanishqTak 2 месяца назад +4

      This made me laugh.....

    • @insu_na
      @insu_na 2 месяца назад +3

      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

  • @Kuukunen2
    @Kuukunen2 2 месяца назад +26

    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 Месяц назад

      Nice.

    • @painsama2791
      @painsama2791 Месяц назад

      Lmao​@@luciferzero8164

    • @aleksanderwasowicz8499
      @aleksanderwasowicz8499 Месяц назад +2

      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 Месяц назад +1

      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 18 дней назад

      @@tirushone6446 “Case Number 999:”
      lol just imagine

  • @toyb-chan7849
    @toyb-chan7849 2 месяца назад +22

    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  2 месяца назад +2

      oh I see, interesting. Thank you

    • @hyde4004
      @hyde4004 Месяц назад

      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.

  • @DFsdf3443d
    @DFsdf3443d 2 месяца назад +57

    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 2 месяца назад +8

      They also force you to be exhaustive and cover all cases

    • @Brad_Script
      @Brad_Script 2 месяца назад +1

      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 2 месяца назад +8

      @@bloom945 No they don't. The compiler will happily accept a switch statement without all cases covered and without a default case.

    • @DistantJacob
      @DistantJacob 2 месяца назад +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 2 месяца назад +2

      @@slyfox3333 yeah in trash language but in any modern language you need to be exhaustive

  • @marinesciencedude
    @marinesciencedude 2 месяца назад +68

    Does the universe explode when two RUclipsrs with 'Low Level' in their name appear in the same video? probably not but the frequency of such a naming scheme is curious

  • @sealsharp
    @sealsharp 2 месяца назад +30

    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 2 месяца назад +3

      Also CPUs are so much more complex nowadays they can't even calculate exactly how long an instruction takes

    • @mytech6779
      @mytech6779 Месяц назад

      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 Месяц назад +1

      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.

  • @markuspfeifer8473
    @markuspfeifer8473 2 месяца назад +16

    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 2 месяца назад +2

      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 2 месяца назад +17

    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 2 месяца назад +2

      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 2 месяца назад +5

    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  2 месяца назад

      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 2 месяца назад +3

    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.

  • @voodoo5191
    @voodoo5191 2 месяца назад +40

    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  2 месяца назад +11

      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 2 месяца назад +5

      @@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 2 месяца назад +6

      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 2 месяца назад +2

      ​@@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 2 месяца назад +1

      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.

  • @Vdevelasko
    @Vdevelasko 2 месяца назад +6

    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.

  • @Jarikraider
    @Jarikraider Месяц назад +4

    I pretty much only use switch statements when I'm feeling all fancy.

    • @yukizensho6603
      @yukizensho6603 Месяц назад +1

      switch statements are easier to read in some cases

  • @TheMaither
    @TheMaither 2 месяца назад +16

    if < switch < if constexpr

    • @sledgex9
      @sledgex9 2 месяца назад +15

      "if constexpr" is its own category. It's like a glorified "ifdef". (I don't mean it in a bad way)

    • @cristiandecu
      @cristiandecu 2 месяца назад

      @@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 2 месяца назад

      @@cristiandecu "if constexpr" is different than simple "constexpr". It (if constexpr) prunes code too.

  • @cryonisc
    @cryonisc 2 месяца назад +1

    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.

  • @Jakobg1215
    @Jakobg1215 2 месяца назад +17

    For rust I use the match statement lot more than if statement mostly due to it looks nicer with enums.

    • @SMorales851
      @SMorales851 2 месяца назад +1

      Not only does it look nocer, it is much more powerful, mainly because of the destructuring

    • @xphreakyphilx
      @xphreakyphilx 2 месяца назад +1

      You can get the destructuring with if let statements, but match statements are definitely way nicer to read and write

  • @ivlis.w8630
    @ivlis.w8630 2 месяца назад +18

    Yanderedev was right.. 💀

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад +27

      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.w8630
      @ivlis.w8630 2 месяца назад

      ​@@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 2 месяца назад

      ​@@lowlevelgamedev9330 from what i remember, c# also optimizes from around a certain number of if statements into a switch statement

    • @timmygilbert4102
      @timmygilbert4102 2 месяца назад

      ​@@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 2 месяца назад

      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.

  • @edgarkhachatryan9992
    @edgarkhachatryan9992 2 месяца назад +1

    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

  • @Kiyuja
    @Kiyuja 2 месяца назад +1

    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...

  • @ramoncf7
    @ramoncf7 2 месяца назад +6

    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 2 месяца назад +1

      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 2 месяца назад

      ​@@TheJGAdamsi'm a little confused, you can have debug info on when compiling with optimizations?

    • @somenameidk5278
      @somenameidk5278 2 месяца назад

      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 2 месяца назад +1

      @@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 2 месяца назад

      @@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

  • @1ups_15
    @1ups_15 2 месяца назад +1

    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

  • @severgun
    @severgun 2 месяца назад +3

    9:16 10% is HUGE difference.

  • @Julienraptor01
    @Julienraptor01 2 месяца назад +2

    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

  • @harald4game
    @harald4game Месяц назад +1

    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.

  • @StrielokPLsz
    @StrielokPLsz 2 месяца назад +1

    in embedded world you have a ton of proprietary compilers with code obsolete beyond all recognition or with paid optimizations like XC8 from microchip

  • @_M_643
    @_M_643 Месяц назад

    I think generally it's still good practice to write switch statements where possible. They also look pretty clean.

  • @templeofdelusion
    @templeofdelusion 2 месяца назад +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  2 месяца назад

      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 2 месяца назад

      ​@lowlevelgamedev9330 That misses the point. If profiling finds a bottleneck, 10% can be meaningful. That bottleneck can easily be switch/if logic.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  Месяц назад

      @@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

  • @wertigon
    @wertigon Месяц назад

    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.

  • @robstamm60
    @robstamm60 Месяц назад

    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.

  • @nahmanbop9248
    @nahmanbop9248 2 месяца назад +14

    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 2 месяца назад

      could you elaborate on what you mean by the last statement about state machines vs ifs?

    • @p0t4toePotato
      @p0t4toePotato 2 месяца назад +2

      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 2 месяца назад

      switch can actually be optimized into an if/else statement when the number of cases are very low

  • @DLCSpider
    @DLCSpider 2 месяца назад

    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.

  • @insentia8424
    @insentia8424 2 месяца назад +1

    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.

  • @Juss_Chillin
    @Juss_Chillin 2 месяца назад

    Thank you for finally ending this long lasting discussion! Great video

  •  2 месяца назад

    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.

  • @andreitgk4748
    @andreitgk4748 2 месяца назад

    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.

  • @Oler-yx7xj
    @Oler-yx7xj 2 месяца назад +1

    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

  • @DeathSugar
    @DeathSugar 2 месяца назад

    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.

  • @Alexi_Blue
    @Alexi_Blue 2 месяца назад

    I love the Aria Math while explaining the Gauss sum lol

  • @joemama-j8b
    @joemama-j8b 2 месяца назад +1

    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.

  • @jannegrey593
    @jannegrey593 Месяц назад

    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 2 месяца назад

    C#/Net definetly compiles switch statements to if else chains unless you have a huge number of cases :)

  • @oskar_schramm
    @oskar_schramm 2 месяца назад

    Amazing video! You know what is even faster and branchless, atleast with Shader code -> using lerp as an if statement ;)

  • @SianaGearz
    @SianaGearz 2 месяца назад +3

    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.

  • @harryvpn1462
    @harryvpn1462 2 месяца назад +13

    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 2 месяца назад +1

      those people didn't make a game with 0 features that runs below 60fps on modern hardware...

    • @Brad_Script
      @Brad_Script 2 месяца назад +2

      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 2 месяца назад

      @@templeofdelusion and specifically targeted at freaks too lol

  • @peppidesu
    @peppidesu Месяц назад

    never underestimate your compiler, folks

  • @jagd_official
    @jagd_official 2 месяца назад

    I find the switch statement an eye sore for my eyes. Code needs to be beautiful to the eyes, artistic indeed

  • @uxel-g9y
    @uxel-g9y 2 месяца назад

    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.

  • @brianb2308
    @brianb2308 2 месяца назад

    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

  • @Xankill3r
    @Xankill3r 2 месяца назад

    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.

  • @110SEBA15
    @110SEBA15 2 месяца назад

    I'm just here to say that I heard the Minecraft music immediately and assumed I had Minecraft open. 😂

  • @the-pink-hacker
    @the-pink-hacker Месяц назад

    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 2 месяца назад

    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.

  • @theevilcottonball
    @theevilcottonball 2 месяца назад

    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....

  • @flameofthephoenix8395
    @flameofthephoenix8395 2 месяца назад

    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.

  • @dungeon4971
    @dungeon4971 2 месяца назад

    I looked at the title and thought to myself so switch statements are faster than if statements in c

  • @lensy6
    @lensy6 2 месяца назад

    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.

  • @alihene2225
    @alihene2225 2 месяца назад

    Switch is definitely useful in embedded or osdev where optimizations can sometimes (rarely though) have negative effects

    • @Brad_Script
      @Brad_Script 2 месяца назад

      the only reason people hate switch is the mandatory "break"

  • @atackhelikopter4303
    @atackhelikopter4303 2 месяца назад

    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  2 месяца назад

      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 2 месяца назад

      @@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 2 месяца назад

      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

  • @vulnoryx
    @vulnoryx 2 месяца назад

    I will never be as smart as those people that made the compilers

  • @sonphisica3136
    @sonphisica3136 Месяц назад

    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  Месяц назад

      rand is kinda cheaply implemented it is just a few operations so it is good

  • @flameofthephoenix8395
    @flameofthephoenix8395 2 месяца назад

    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  2 месяца назад +3

      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 2 месяца назад

      @@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.

  • @sinom
    @sinom Месяц назад

    10:25 LLL is a C programmer. And as a C programmer he probably doesn't turn on optimizations since those will hust "obfuscate the output"

  • @yiranmushroom
    @yiranmushroom 2 месяца назад

    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.

  • @omegahaxors9-11
    @omegahaxors9-11 Месяц назад

    People who say "this is faster that is faster" have clearly never looked at decomp and are completely taking out of their ass.
    Work with your compiler: Write readable code first and only make changes when your compiler fails to produce optimal instructions.

  • @kubolor1234
    @kubolor1234 2 месяца назад +2

    As someone with ADHD I prefer switch statements

  • @tutacat
    @tutacat Месяц назад

    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.

  • @ThaitopYT
    @ThaitopYT 2 месяца назад

    *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.

  • @nordgaren2358
    @nordgaren2358 2 месяца назад

    Relying on the compiler to optimize your if statement when it should be a switch statement, is asking for trouble.

  • @SpiraSpiraSpira
    @SpiraSpiraSpira Месяц назад

    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

  • @Zullfix
    @Zullfix 2 месяца назад

    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 2 месяца назад

      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 2 месяца назад

      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  2 месяца назад +1

      yoo thanks for testing it and letting me know, so it seems like in c# switch is faster

    • @Zullfix
      @Zullfix 2 месяца назад

      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 2 месяца назад

      ​@@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)

  • @JosephBlade.
    @JosephBlade. Месяц назад

    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

  • @milasudril
    @milasudril 2 месяца назад

    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  2 месяца назад

      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

  • @Spartan322
    @Spartan322 2 месяца назад +5

    First off a compiler cannot optimize runtime data in your example in many cases, for example if you're writing generalized data processing that you need to be really fast, or a database, a switch in many cases will be faster. Switches and ifs only look similar under like 10 or 15 cases in most compilers, but once you start to get more, the compiler tends to give up more and the jump table starts to become radically faster, (and the compiler starts to become unable to properly optimize that many cases for the if because of logical reasons, also the cases are rarely simple math cases the compiler can work out) partly because there is a limit to if statement analysis and because a compiler cannot always inherently optimize if branches for runtime data, it may but this is not inherent and it tends to suck as you get more if statements.
    I'll give you a really simple case where switch will always be faster, a switch over an enum where the default case has undefined behavior (like std::unreachable) which in large enums will always be faster. The compiler will usually by default "build" empty default cases if you don't do this which is a proven slowdown in hot code, by putting in a default case with undefined behavior you're telling the compiler explicitly that "this should never exist" which if the presumption were wrong will cause all sorts of problems, but if the presumption can't be wrong, it does increase performance by giving the compiler a definite end to the switch. This is likely another thing you're also missing, every single one of your switches have a default case that is not optimized out, the compiler has no idea if the input data to the switch is bounded so it prepares for the worst case, that being supporting an unchecked/default case.
    I think you don't understand what they mean by switch is faster, because it absolutely is, you're demonstrations may not have enough cases to demonstrate that and ignore side effects entirely and you leave open too easy a path for the compiler to optimize the if away, but in cases where the if can't be optimized away, which happens a lot in production code, switch is always faster. When the if can be optimized, sure it could end up as fast as the switch, but when it can't the switch is guaranteed to be faster. So a switch guarantees performance, for the if its a possible suggestion. All it takes is one side effect in an if statement and this optimization for ifs dies, because compilers have to keep side effects in optimized code, and there is no way to do so without going the slow route with if statements.
    Don't rely on benchmarks to prove a point for production code, that's what profiling is for, and every time I've profiled switch with deliberate optimizations, it was faster then had I used if statements. Benchmarks don't show real use cases, they are functionally useless.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      I mean I also read asembley and I showed compiler logs and also tested with a lot of cases. If you want you can test with more cases and let me know if you find a different result. It makes no sense for a compiler to not be able to optimize an if chain just because they are too many cases, and be able to optimoze an if. Internally it will just run an algorithm to check if that if chain can be a switch, and its not something complicated

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      hm I will try the thing with the default case. I also with that. But I will check the unreachable version tho. After a lot of tests all the if statements created a jump table.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      or you can message me on discord if you want to investigate together, I have also tried to test side effects in the tests, but maybe I am missing something

  • @olbluelips
    @olbluelips 2 месяца назад

    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

  • @AURORAFIELDS
    @AURORAFIELDS 2 месяца назад

    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  2 месяца назад

      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.
      ```

  • @severgun
    @severgun 2 месяца назад

    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.

  • @SnakeEngine
    @SnakeEngine 2 месяца назад +2

    The switch statement uses one if-check (for a jump when the switch-value is invalid) and 2 jumps (one jump to the case, and second to break out from it) using assembly. In short, it executes 3 of the costly operations. So if you have a chain of 4 or more if-statements, the switch will be faster.
    This point is of course irrelevant if the compiler is smart enough to convert the if statements to a jumptable implementation.

  • @Nanagos
    @Nanagos 2 месяца назад

    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.

  • @aldi_nh
    @aldi_nh 2 месяца назад +1

    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

  • @timmygilbert4102
    @timmygilbert4102 2 месяца назад

    I avoid switch statement because i can do:
    State.current = object.state;
    State.current.execute()
    😂 Much cleaner, much clearer 😊

  • @CottidaeSEA
    @CottidaeSEA Месяц назад

    Commenting midway through the video, but I'm pretty sure the compiler just uses switch logic if it detects you're only comparing one value and just handles them the same way.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  Месяц назад

      yes, it uses the same code for the switch and if, asembley generation

  • @anon_y_mousse
    @anon_y_mousse 2 месяца назад

    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.

  • @nangld
    @nangld 2 месяца назад

    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  2 месяца назад

      you can find most of my tests in the description. I checked them by hand by looking at the asembley and comparing the speed

  • @Brad_Script
    @Brad_Script 2 месяца назад

    I still think you should use switch with enums, the compiler can detect if you didn't handle all cases.

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      yo I am not against switch, just think its silly to say that just by using switch your code will be much faster

  • @xeakpress
    @xeakpress 2 месяца назад

    Yea, but like... switch statments LOOK cooler then if statement spaghetti so like yea.
    Nah, im kidding. I just like switch statments, and im comfortable using them and reading them. Didn't know If statements were that JUICED

  • @borstenpinsel
    @borstenpinsel 2 месяца назад

    Why would switch be faster? In the end, it all boils down to assembly where there is no switch anyhow. In fact they are complex ifs either (unless it's arithmetical and the compiler tutns it into a multiplication/addition). Only comparisons with jumps.

  • @elias-ou2sp
    @elias-ou2sp 2 месяца назад +2

    "switch is not faster than if" everything wrong with programming in a nutshell

    • @Brad_Script
      @Brad_Script 2 месяца назад +3

      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.

  • @brynnerjayantiquesa7441
    @brynnerjayantiquesa7441 2 месяца назад

    Well in low level learning video, you might have overlooked the optimization level like -o2 in argument in gcc

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      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

  • @tutacat
    @tutacat Месяц назад

    So, it's not faster because it just tests every condition because that is faster than branch prediction errors.
    Oh boy, Python has added switch statements!

  • @moestietabarnak
    @moestietabarnak Месяц назад

    So, without optimization, switch are faster, with they are equal --> use switch and it work fine even when not optimized
    Also, when I see a switch and I'm looking for a specific case, i got right to the switch label to read the instructions, If I see a bunch of IFs ... I have to read ALL IF to make sure it does not do something else than the switch

  • @enriquedelacal2814
    @enriquedelacal2814 2 месяца назад +1

    theyre only faster with the biggest level of optimizations on (O3) which basically no one uses especially in production code

    • @lowlevelgamedev9330
      @lowlevelgamedev9330  2 месяца назад

      where do you come up with this things? I don't think there is a single company that doesn't ship production code without O3

    • @enriquedelacal2814
      @enriquedelacal2814 Месяц назад +2

      @@lowlevelgamedev9330 It would be very stupid to ship production code with O3 since many of the optimizations that are implemented on that optimization level rely on undefined behavior and assumptions that can essentially skip whole sections of your code. Where do you come up with these* things?

    • @sonicjoplus
      @sonicjoplus 4 дня назад

      @@lowlevelgamedev9330 Optimization can be dangerous if it is at a very high level, as it may be able to generate assembly that can create a buggy mess of a program. In fact, if you looked that up, you'd find that there is a point where O3 is not needed and creates actual problems.

  • @ry6554
    @ry6554 Месяц назад +1

    Switch is not faster.
    It's better.

  • @vast634
    @vast634 2 месяца назад

    You performance problems likely will not stem from using if instead of switch anyways. There is usually easier apples to pick to improve performance.

  • @xijnin
    @xijnin 2 месяца назад +1

    The switch statement is or people who wanna make else ifs without people laughing of them

    • @Tealen
      @Tealen 2 месяца назад

      Whats wrong with else ifs

    • @anon1963
      @anon1963 2 месяца назад

      nothing ​@@Tealen

    • @Tealen
      @Tealen 2 месяца назад

      @@anon1963 lol then why would people laugh

    • @anon1963
      @anon1963 2 месяца назад

      @@Tealen they wouldn't, I work with great c++ devs, nobody cares whether you use switch or if. as long as it works correctly