The Importance of Scalable Code // Code Review

แชร์
ฝัง
  • เผยแพร่เมื่อ 21 ก.ย. 2024

ความคิดเห็น • 247

  • @TheCherno
    @TheCherno  ปีที่แล้ว +12

    Thanks for watching! ❤
    To try everything Brilliant has to offer-free-for a full 30 days, visit brilliant.org/TheCherno. The first 200 of you will get 20% off Brilliant’s annual premium subscription!

    • @goodgoyim9459
      @goodgoyim9459 ปีที่แล้ว

      what are your thoughts on vim? possible to develop video games on it like with vstudio?

    • @amoldhamale3202
      @amoldhamale3202 ปีที่แล้ว

      @@goodgoyim9459 You didn't ask me so probably shouldn't be answering. Vim's a great tool but not for large projects in my opinion. You don't necessarily need an IDE like Visual studio, a code editor like vscode would be just fine. However on vim, you will miss some great extensions and intellisense features of vscode. I generally use vim for quick refactoring, editing and writing small programs. There's nothing faster than vim when it comes to refactoring and editing if you know the right set of commands.

    • @eluddite889
      @eluddite889 ปีที่แล้ว

      I hope you're not making fun of my Chess app. There's a limited number of moves so it makes sense to use multiple if statements.

  • @the_fl3dd0x
    @the_fl3dd0x ปีที่แล้ว +375

    I would absolutely like to see you actually implement the things you talk about.

    • @hourglass2836
      @hourglass2836 ปีที่แล้ว +2

      this

    • @ultimatesoup
      @ultimatesoup ปีที่แล้ว +1

      The best way to do this is to have a common base type for all objects with no virtual. You will get different behavior by adding different components to different objects. So maybe an object has a camera component, a sound component and a render able component. The object will just iterate through those and call the update function on each of those components. This way every thing can be in one object manager and you don't have all those repeated containers

    • @nevemlaci2486
      @nevemlaci2486 หลายเดือนก่อน

      ​@@ultimatesoup That isn't what any half-competent game does tho

    • @JOHN-um2
      @JOHN-um2 3 วันที่ผ่านมา +1

      That’s the thing. Half the things he says don’t come to fruition in a real environment due to constraints and HIS IDEAS SUCK.

  • @CatzHoek
    @CatzHoek ปีที่แล้ว +174

    Maybe not always but it would be cool to see the actual code you would produce for certain things once in a while.

  • @Dr-Zed
    @Dr-Zed ปีที่แล้ว +247

    I love combining random adjectives with the word "code"
    - scalable code
    - clean code
    - sad code
    - trashy code
    - delicate code
    - hesitant code
    - cute code
    - sassy code
    - perfect code
    - strict code
    - expensive code
    - shiny code
    - resilient code
    - disgusting code
    - repulsive code

    • @lazergenix
      @lazergenix ปีที่แล้ว +45

      Yeah, I see what you're saying, but honestly super-diffraction hyper euclidian code would really be what you would need to strive for in any code project. If you do not achieve sonic kinetisis, then you won't be able to even get to the stage of late giga-photosynthesis; something that is rarely even mentioned nowadays. The tips I ALWAYS use in any of my code projects, is to always make sure to inject the right amount of hydro-classes to make sure my structs always retain their polymorphism, and to NEVER intoduce morpho-incapitance, as it will always lead to rapid decay of the code fibers. But thats just me.

    • @christopheriman4921
      @christopheriman4921 ปีที่แล้ว +10

      @@lazergenix Hmm yes, this definitely makes perfect sense. Hydro-classes probably would have to do with when you get water in your computer.

    • @rafa_br34
      @rafa_br34 ปีที่แล้ว +5

      It's missing the "- resilient code"

    • @Dr-Zed
      @Dr-Zed ปีที่แล้ว +3

      ​@@rafa_br34 updated the list

    • @peezieforestem5078
      @peezieforestem5078 ปีที่แล้ว +6

      adjectives are all well and good, but what about "zero code"? I heard it's the next big thing.

  • @Squirrelies1
    @Squirrelies1 ปีที่แล้ว +30

    As someone who is proficient at C# but fairly new to C and C++, I find your content helpful. I don't fall into the pitfalls of this video per-se but your content really helps me coming from another background and space.

  • @ale-lp
    @ale-lp ปีที่แล้ว +70

    The world needs more data oriented examples please. I'm still trying to wrap my head around it

    • @Mini_CS
      @Mini_CS ปีที่แล้ว

      I have a video on my channel that might help (if you are still having this problem. I know its been a month)

    • @ale-lp
      @ale-lp ปีที่แล้ว

      @@Mini_CS Yup, I'm still struggling with this concept since I don't have enough time to put into learning this kind of stuff, my day job is just boring. Will take a look for sure, thanks!

    • @MrHaggyy
      @MrHaggyy ปีที่แล้ว

      Well the basic idea is simple. How much data do i have? How many functions do i have?
      And how does the controlflow of my program look like when i iterate over every datapoint and decide which function to apply or iterate over every function and check to which datapoint it applied.
      The simpler the structure the better.

  • @stephenelliott7071
    @stephenelliott7071 ปีที่แล้ว +52

    An Entity Component version would be very helpful, as would performance profiling with cache misses vs the current code IMO.

  • @BulletproofOutlaws
    @BulletproofOutlaws ปีที่แล้ว +17

    Hey Cherno! Two time-saving ideas for you for rewriting code in these vids:
    1) You could just use simplistic pseudo-code, skip a bunch of syntax and just rough out the overall idea…then we still have to do some problem solving to turn it into usable code, but it would be more clear than trying to verbalize what you’d do (drawings like you sometimes do would work too!)
    2) ChatGPT has been a big help to me for learning, maybe you can have it spit out or refactor code for you, getting an end result close enough to what you would do to explain things like “make these objects into an ECS”
    I find refactoring vids one of the most useful resources because we all make a lot of the same mistakes at first and watching someone with experience step through refactoring as they explain their decisions is a huge help to get from beginner to intermediate/advanced

  • @РайанКупер-э4о
    @РайанКупер-э4о ปีที่แล้ว +15

    I would love to see this code actually modified using your recommendations.

  • @Treborbobuk
    @Treborbobuk ปีที่แล้ว +7

    To answer the question about whether it's worth you re-writing stuff on camera, I think that could BE the video - where I work the devs often make code change suggestions as part of the code review (even though I tend to discourage them doing that in the cases where it means a more senior dev ends up writing the code for a junior) It would be great to see what you would do vs what was done to compare and contrast. Love your content and I really enjoy these code reviews!

  • @urugulu1656
    @urugulu1656 ปีที่แล้ว +16

    no the birds do not need inheritance. just add a bitfield for the colors instead . this would also enable multi colored birds which would likely be a fun game mechanic. and for the thing with the numbers being added or subtracted from the score just put these in an array that can be indexed by the bitfield value being casted to an integer.. (but maybe i am just too deep into the microcontroller / c99 way of thinking)

    • @xeridea
      @xeridea ปีที่แล้ว +2

      I was thinking same thing. All birds the same class, but just reference an array based on bird type for values.

    • @legitjimmyjaylight8409
      @legitjimmyjaylight8409 ปีที่แล้ว +1

      Or use the strategy pattern, or even just an entity component system.

    • @soniablanche5672
      @soniablanche5672 ปีที่แล้ว

      or just put the score as a property of bird

    • @yiranmushroom
      @yiranmushroom 4 หลายเดือนก่อน

      You should use inheritance here if you want to do it in a more C++ way.

    • @nevemlaci2486
      @nevemlaci2486 หลายเดือนก่อน

      ​@@yiranmushroomdoing it with inheritance is very inefficient tho, loads of cache misses 🤷‍♂️

  • @omarmagdy1075
    @omarmagdy1075 ปีที่แล้ว +11

    This is hands down one of the most educational series for programming I have seen. I have acquired some many good tips out of this series and it affected my day to day coding to the better. Keep up the amazing work.

  • @HenryLoenwind
    @HenryLoenwind ปีที่แล้ว +2

    There's also a halfway way of doing this. You can put all the common stuff into a base class (or even struct) and then include an untyped pointer to the specific class for that object (along with a type marker so you know what to cast it to) in it. That way, your common code works for all game objects, and they are tightly packed in memory. When including a "dead" flag, you can even use a dumb array for game objects that are not extremely short-lived. Including a deletion counter and a garbage collection routine to pack the array when it had too many deletions also makes sense.
    I like to write my own collection classes that know what kind of data they hold. This also allows me to do such trickery lie splitting the stored objects into multiple lists or filtering the objects by type (without looping over all of them because the Collection class can cheat with array slices or sub-lists by object type it keeps in sync with the main list). While the code inside that collection isn't really that different from what would be outside when using generic lists, being able to call "give_me_all_movable_and_collideable_objects_that_collide_with(player)" makes the high-level code so much clearer to read and makes it easier to change the way the data is stored easier as it's all in one place.

  • @APaleDot
    @APaleDot ปีที่แล้ว +1

    > Is zero an even number?
    The answer is a definitive "yes"! It satisfies every property that even numbers have:
    - It's an integer
    - It's a multiple of two
    - It lies between two odd numbers
    - Any number multiplied by it results in an even number (because 0 is even)

  • @aj-jc4cv
    @aj-jc4cv ปีที่แล้ว +4

    Entity component system rewrite would be super useful. These videos are gold.🏅

  • @Domix-nh8ws
    @Domix-nh8ws ปีที่แล้ว +12

    Please rewrite it with an ECS, or something similar it would be amazing to see the comparison.

  • @fyvefouroh
    @fyvefouroh ปีที่แล้ว +16

    You should use a tool that measures cache hits and misses on this project for fun. I think it would be interesting to see

  • @m4rt_
    @m4rt_ ปีที่แล้ว +12

    21:45 I would create one class/struct for the Bird, and an enum for what type/color it is, then have some logic either inside the Bird, or in the use of the bird that changes the behavior based on the type/color... though I prefer the more C way of doing things over the C++ way.

    • @kgnet8831
      @kgnet8831 ปีที่แล้ว +2

      it is not a question of c versus c++ way ... with your implementation you could instanciate the birds as values, so std::vector or Bird[] (the c way) and get memory locality and that makes a c AND a c++ dev happy 😄

    • @necuz
      @necuz ปีที่แล้ว +5

      Right and if the only things that are going to differ between them is how score/lives changes on a collision, you can turn that into /blazing fast/ table lookups using the enum as index.

    • @m4rt_
      @m4rt_ ปีที่แล้ว

      @@necuz indeed

    • @Turalcar
      @Turalcar 3 หลายเดือนก่อน

      @@necuz It won't be faster than grouping the birds by behaviour like the author does. I would extract a lot of the copy-pasted stuff though.

  • @darkthunder301
    @darkthunder301 ปีที่แล้ว +1

    Assuming all the classes from the birds to the sparks are obstacles the player needs to avoid, it might be easier to abstract the collisions into "check if player rectangle collides with generic object rectangle," whatever is used to represent the object is just a pretty dress for a box.

  • @xeridea
    @xeridea ปีที่แล้ว +3

    I vote for rewriting, you are very fast at code, you explain it anyway, which takes time.
    Less memory isn't always faster, in fact, many tasks perform better if you cache things so you aren't constantly recomputing, especially trig functions. If my game I cache square root values for my lighting system, giving a substantial speedup.
    Reducing code duplication can increase performance, since bloated code is less likely to fit in the CPU instruction cache, which is fairly small.

    • @mzxrules
      @mzxrules ปีที่แล้ว

      it really depends on the hardware whether code duplication is fast/slow, and also whether the problem necessitates that your code run fast. I've been recently coding an Atari 2600 game in 6502 asm, and the CPU is so slow (especially during rendering) that there are many instances where you'll waste several bytes of ram in order to save a few CPU cycles, either by unrolling loops (since conditional checks are slow) or avoiding modular solutions to problems (subroutines are slow and cost ram).
      If you're writing code in a high level language, the compiler is making it's own judgement calls on whether to duplicate code at the machine level anyway. In theory, that utils::Collisions function could be inlined everywhere it's called if the compiler deemed it efficient to do so, though I'm not confident if such a thing would be done in practice.

  • @MrHaggyy
    @MrHaggyy ปีที่แล้ว

    I have written code similar to the isEven number on purpose. We had 4 or 8 hardware ports and initialy there was a for loop iterating over i ports. The benefit of having 4 or 8 explicit is that i can check split second which of them where present at specific places in code. You couldn't mess around wirh the wrong hardware accidently and we didn't had to store the iterator in memory.
    But it's still good practice to keep things scalable. It's quite easy to make working code explicit once you have the necessary requirements to do so.

  • @Satook
    @Satook ปีที่แล้ว

    Seeing it done is always helpful. I think watching each tweak and how is actually really important.

  • @megak550
    @megak550 ปีที่แล้ว

    Hello, can someone explain why the nesting is done? I mean std::vector.

    • @machimanta
      @machimanta ปีที่แล้ว

      This means that it's a vector containing unique pointers of type 'T', where T is from the 'template '. Templates are a form a "metaprogramming" where at compile time 'T' is expanded into whatever specific types actually use the implementation throughout the codebase

  • @literallyfiction
    @literallyfiction ปีที่แล้ว +4

    Curious what your thoughts on Casey Muratori’s take on ‘clean code’, Cherno

    • @jamesmnguyen
      @jamesmnguyen ปีที่แล้ว

      Cherno would probably agree on some points but not others but hard to say exactly.

  • @danielbaulig
    @danielbaulig ปีที่แล้ว +1

    12:20 Quick point of feedback. My understanding is that you build game engines and for engines and other pieces of product infrastructure it appears performance probably always beats readability and other maintainability factors. The idea is I guess that you can't know how your engine will get used in an actual product and how much real performance that product will need.
    However, when building products (instead of infrastructure), there is a sufficient level of performance at which point trading more performance for other factors like maintainability, readability, etc becomes utterly useless and will be net negative for the product and it's users.
    Just something I wanted to call out. More performance is not always better. I'm sure you're aware of this, but I think it's worth calling out to the audience, too.

    • @humanrye8696
      @humanrye8696 ปีที่แล้ว

      Right, without maintainability code get rotten very fast. The cost of development for every bugfix, every new feature skyrockets and the entire solution becomes unusable at some point.
      Performance focused code can still be used, but it should be easily replaceable if needed and should not affect higher layers.

  • @StevenMartinGuitar
    @StevenMartinGuitar ปีที่แล้ว +2

    Would be cool to see the changes made and a diff. If people are concerned it would be too long then youtube has a super cool function where it lets you skip forward in a video

  • @stephenyork7318
    @stephenyork7318 ปีที่แล้ว

    Just up to 3:50. What comes to mind already is you could use some hash tables, Keyed by bird colour. Key by green then have the other colours that could be hot, the next key would return the scores.

  • @briannoel7398
    @briannoel7398 2 หลายเดือนก่อน

    Maybe some demonstration with pseudocode would be useful, but I don't think a full implementation would be necessary. You're very good at explaining these things so I don't have trouble following along.

  • @designator7402
    @designator7402 ปีที่แล้ว +4

    0 does fulfill all requirements of being an even integer, so yes, 0 is considered even in most circumstances.

  • @shadeblackwolf1508
    @shadeblackwolf1508 ปีที่แล้ว

    For an inheritance_low implementation you could ofcourse just add an interface, not even a base class, allowing clustering them together. Delegate the hitbox to a hitbox object, reusing code isn't hard, and even if you don't like inheritance, that's not an excuse not to use composition instead

  • @larryd9577
    @larryd9577 ปีที่แล้ว

    I'm very keen on seeing the impact of the refactoring considering cache-hits/-misses.

  • @dougpark1025
    @dougpark1025 ปีที่แล้ว

    Tools at your disposal for solving the problems in this video. Inheritance, as you mentioned, making things derive off of a base class where you have common interfaces. Templates. If you can't or don't want to use abstraction, a template for something like your collide function could be implemented that assumes certain methods are in a class. This could be ever so slightly faster than inheritance, but maybe doesn't give you the nicety of changing how something works on a per derived class basis. Functional programming, lambda etc. This can be useful if for example you need a different way of detecting collision, same idea as doing a std::sort. One or another of these isn't necessarily the best way way.
    The locality in memory of data is an often missed performance improvement. Does the application create and destroy objects often enough to need pointers? Maybe the overhead of adding and removing items from a contiguous block of memory isn't as much as you think. That needs a benchmark to decide. My gut instinct is to start with contiguous memory. But that may not be the right answer. std::vector has a reserve option for if you need to grow a contiguous block. One of my standard optimization techniques is to collect then process, often with a sort involved to speed up processing. This may or may not be appropriate in all cases.
    The locality in memory idea goes back to the days when computers often didn't have enough memory to store all of the data being processed. Back in those days, before most of you were born, a lot of data was stored on disk then read into memory in blocks processed, then the results were written back out. If you think of your memory as a slow hard drive or an Internet connection, then you are on the right track to understand the concept.

  • @Asto508
    @Asto508 ปีที่แล้ว

    Second video I've seen of you and although I'm not learning anything new in particular, I think it's nice to see someone else having similar thought processes going on when looking at this code.
    As others have highlighted, it would have actually been interesting to profile this code against a refactored version of it to see whether locality rolls out the way you (and I) assume it does.
    I've written similar stuff in the past using vectors holding unique_ptr without really thinking about the implications on the memory layout, but I haven't touched C++ in almost a decade to be honest, so a direct comparison for this particular case would actually be very nice.

  • @avtem
    @avtem ปีที่แล้ว

    13:00 lmao, it made my day
    edit: please keep talking about memory it's really interesting

  • @pederslothzuricho7685
    @pederslothzuricho7685 ปีที่แล้ว

    10:58 0 is not a number, neither even nor uneven, its a concept we pretend is a number to make maths work, 0 is in fact the absence of everything. Hence why you cannot divide by zero. when we zero-index, we actually use zero as 1 and pretend that absence doesn't exist. Absence of power in that sense is Zero, but numerically in binary terms we usually apply 0 as 1 and then pretend the 1 is a pretending of the absence we symbolise with 0. But zero is not a number it does not exist.

  • @tambow44
    @tambow44 ปีที่แล้ว

    Is Zero an even number? Is zero even a number at all? The Mathematics department back in uni had a LOT of debates about this.
    Great lecture btw, ty Chernzy.

  • @lombeelo8780
    @lombeelo8780 ปีที่แล้ว

    As example, to show the answers, you can rewrite code and show diff/two windows with two versions of file and describe the changes.

  • @CallousCoder
    @CallousCoder ปีที่แล้ว

    All those else if's could be done even without a modulo by just doing a logical and 1. This is actually what most compilers optimize it as as well!
    I frankly don't understand how people even come up with such an incredible long else if list! But they are there!

  • @hanspeterbestandig2054
    @hanspeterbestandig2054 ปีที่แล้ว

    Thank you very much, Sir! Very well explained!
    What I love in special is that you address the aspect of readability of code among the importance to have a look at the memory consumption of the algorithm. These are very important topics!
    Well, since I‘m an embedded Developer - that one, that is use to dig in the "ancient mud" of cpu- and chip registers 😁 - I am used to work with *very* small Computersystems. Stuff with around 64kB and often less of SRAM! Not Gigabytes! KILO- Bytes! Often not more. Today’s PC based systems almost have x times of this memory available just for a Threads stack frame, what my System has as its whole…Furthermore these Systems run just with about 100 MHz! NOT GIGA Hertz ;-) So a clear SW architecture with the focus on performance and an economic memory layout is an absolute requirement on these Systems. Robustness: These Systems are used to run 24/7 for YEARS! Some of them are used in mission critical environments! Hence dynamic memory allocation (malloc/new…) are not used and are sometimes forbidden. However they are used very rarely - often allowed just at the startup of the system to allocate memory. The use of dynamic memory while runtime is not used due to the aspect of memory fragmentation. See I n an embedded System that runs 24/7 it is mandatory that your system will succeed memory allocations *at any time*. Hence on these Systems it is common to use objects/variables pre-allocated in the global memory space which are clearly allocated by the linker. Constant Data then is located in Non volatile and write protected memory areas (FLASH) and data, that need to be changed (Variables, working storage, arrays) are located in fast but sparse SRAM. Remember, we’ve gut just a view KILO Bytes of this in my world of Embedded computing. Nevertheless I‘m a big fan of C++ even on these small Systems. And believe me: All these prejudices about “bloat code due to C++” ( virtual functions with their indirection by vtables are wrong and I’ll need to argue that again and gain.. Just let you give you guys an insight of the life of an Embedded Engineer - a guy that life’s in the mud of code if you like 😊
    And I can everybody recommend to grab an Arduino in order to see, how small a word can be - and how creative one can get just to get its code/idea to run on such a small/ weak system!
    Well, probably one may treat this as some sort of “stay in the monastery” for some months just to purify itself. Think about coding. Purify itself by enforces itself to consciously renounce and find another solution enforced by the limited resource...
    And I'm pretty sure! If one does so he/she will learn a lot! Things you'll always remember and be beneficial for your whole career! 😉 Servus Dirndl und Buam from Munich, Bavaria!

  • @brendandower9021
    @brendandower9021 20 วันที่ผ่านมา

    Yes to re-writing. perhaps in a dedicated series. The Code Refactor series.

  • @NotMarkKnopfler
    @NotMarkKnopfler ปีที่แล้ว

    I'd be very interested to see a re-implementation video. I've been told by others that my code is very easy to understand - but that's because I consciously try to make it as un-sophisticated as possible. Therefore I must admit, I would have taken a similar approach to the author. I found his code very easy to read though admittedly very repetitive - so I think you were quite correct to pick up on it. 👍Also, kudos to the author for 'sticking his head above the parapet'! I know it not really like that, but you know what I mean! 👍

  • @stephanweinberger
    @stephanweinberger ปีที่แล้ว +2

    @5:30 why so complicated? Just use polymorphism, i.e. different Bird-classes. Then the main code would be completely generic for a collision with _any_ type of Bird.

  • @mr.anderson5077
    @mr.anderson5077 ปีที่แล้ว

    Hey Cherno,
    Amazing content!!!
    Please do a probably an hour long video on all the reviews you gave highlighting topics like Data oriented design, cache hits & misses, creating the inheritance system for all the similar components, optimization strategies, etc. We would love to see that in action and may be we'll pay you for investing your stream time.
    Its been ages since the beginning of this channel "FOR ANOTHER VIDEO..." is served proper justice for all the viewers.
    Everybody agreeing to that, plz hit the like below.

  • @paulfrischknecht3999
    @paulfrischknecht3999 ปีที่แล้ว +1

    thanks for this. you should review code that looks good on the surface but could still be improved substantially, not something like this that obviously suffers simply from too much duplication

  • @anon_y_mousse
    @anon_y_mousse ปีที่แล้ว

    I know what you're trying to say with optimizing, but an IsEven function should be a macro that just does &1 on the input to test. Also, as long as it can tell what you're trying to do, every modern compiler will optimize %2 into &1, so any possible debate about using mathematical operations versus unrolling a loop are completely pointless.

  • @JohnSmith-ze7sv
    @JohnSmith-ze7sv ปีที่แล้ว

    The game objects in the program I am writing are built upon ECS.
    The GameObject class is literally a wrapper for an ECS service which handles all of the component, entity and system mappings.
    A lot of C/C++ programmers really have a bent toward structural programming in the likes of low level API's....
    But whenever I use those APIs - I typically just wrap them back up into objects anyway.
    I see why ECS is a thing.
    But developers appear to latch onto certain ideas like it was their bible and guiding princple - as opposed to what it really is.
    A temporary solution to a temporary problem.

  • @KuroKazeZX
    @KuroKazeZX ปีที่แล้ว

    well i already know not to repeat myself, it is more fun to see what you change to make it cleaner and possibly more efficient

  • @jakeoshay
    @jakeoshay ปีที่แล้ว

    28:35, You definitely need to know if the bird is dead or not, so that if it's dead you would abort the check for collision so to not add more points than intended or retract lives when the entity should be already dead.

  • @MasterHigure
    @MasterHigure ปีที่แล้ว

    "hey what's up guys my name is China welcome back to code review Series" Auto-generated captions for the win.

  • @amoldhamale3202
    @amoldhamale3202 ปีที่แล้ว

    We need a dedicated video on cache hits and misses analysis

  • @AgentM124
    @AgentM124 ปีที่แล้ว

    Initially my thoughts on the separate vectors was maybe an explicit update order. Maybe obj of type X has to be updated before type Y. Perhaps you could sort a vector of all entity types by some priority P though instead.
    Or maybe collision has to be handled in a certain order.
    Update/render order imo should make sense implicitly. It should be some property of an entity, or its context that puts it before or after others. E.g. Z position could be a factor. Rather than explicitly handling different entities in different loops.

  • @timturner7609
    @timturner7609 7 วันที่ผ่านมา

    I'm probably not your target audience, but I'd much rather see videos where you move quicker like "this is bullshit. Something like this would be better." And then through the magic of editing you fix it and hit the highlights of why your fix is better than the original. I'm an old dog but I'm always hoping to learn a new trick

  • @roboterbasteln
    @roboterbasteln ปีที่แล้ว

    0 is an even number. But in C++, unlike some other languages like Python, modulo for negative numbers returns negative remainders.

  • @scriptles
    @scriptles ปีที่แล้ว

    I love your video's, excellent work as usual. Keep up the good work teaching us.

  • @Bbdu75yg
    @Bbdu75yg ปีที่แล้ว

    That thumbnail was so funny!😂

  • @maximalgamingnl9954
    @maximalgamingnl9954 ปีที่แล้ว +1

    Hi Yan,
    I have a question about the std::vector of std::unique_ptr's, because you said that the elements 'kind of had to' be heap allocated.
    It really seems like they don't, because of the vector itself behaving more or less as a smart pointer.
    Am I wrong?

  • @gilsonjustjr
    @gilsonjustjr 2 หลายเดือนก่อน

    hi Cherno, which software do you use to write/draw on screen while you present?
    Thanks
    btw, thanks for the great content in C++ series !

  • @Stabby666
    @Stabby666 ปีที่แล้ว +2

    I guess just using return ((x&1)==0); for isEven is the most efficient as mod implies a division? I suppose any compiler would optimise to the bitwise test though.

    • @igorthelight
      @igorthelight ปีที่แล้ว

      You are correct!

    • @hbirler
      @hbirler ปีที่แล้ว

      ((x & 1) == 0) is actually three instructions on x86: and, test, sete
      (~x & 1) is two instructions: not, and
      and yes any sane compiler generally understands what you meant however way you write it and generates the optimal code. Use compiler explorer to check!

  • @cpp_medium_rare3474
    @cpp_medium_rare3474 ปีที่แล้ว +1

    Something that baffles me is that we are in 2023 and we still have people "learning" to dynamically allocate everything in C++. It's not the first time I see these vectors of utterly pointlessly dynamically allocated objects. Every single member of that class should've been stack allocated. Even the "Sparks" instances that derives from "Explosion" are still just in a container by themselves, so... "vector" for crying out loud! And, yes, I understand the argument that should these derive from a base class, then the code would make more sense but that's not the case here. And, again, even the one class that derives from a base class has its own container anyway.
    What person or what book is still teaching beginners to do that? I sincerely would like to know.

    • @JohnSmith-ze7sv
      @JohnSmith-ze7sv ปีที่แล้ว

      Higher level languages are where most people are being on-boarded into programming these days I'd imagine.
      Everything's an object.
      Stack and heap allocation just aren't concepts you're aware of comming from those languages.
      If one could use smart pointers to replicate ones own javascripting prowess in C++ - I can see how that approach would be taken.

    • @cpp_medium_rare3474
      @cpp_medium_rare3474 ปีที่แล้ว

      @@JohnSmith-ze7sv In this instance, what prowess needed replication?

    • @JohnSmith-ze7sv
      @JohnSmith-ze7sv ปีที่แล้ว

      @@cpp_medium_rare3474 I never meant prowess from an objective viewpoint.

  • @ladymushroom9485
    @ladymushroom9485 7 หลายเดือนก่อน

    10:00 if else is to slow for use cases like these. Optimize with a switch statement.

  • @brunosilva-ed4pz
    @brunosilva-ed4pz ปีที่แล้ว +1

    13:16 Some big game devs should learn more about memory... (coff coff Hogwards Legacy coff coff)

  • @avtem
    @avtem ปีที่แล้ว

    Hey, Cherno! Would you like to do a video about outdating code? For example how game engine stops supporting a certain platform and what you do about that as the creator?

  • @AnFunctionArray
    @AnFunctionArray ปีที่แล้ว

    I would just use virtual functions in this context - for loops - become one function and we have collide_action (especially because we have opted to use unique ptrs).

  • @maverikmiller6746
    @maverikmiller6746 ปีที่แล้ว

    This was pretty good. Thanks Chernoman.

  • @IamusTheFox
    @IamusTheFox หลายเดือนก่อน

    I spent way too long trying to over-engineer a better solution to IsEven. All it needed was constexpr and a modulo operator. lol.

  • @Necessarius
    @Necessarius ปีที่แล้ว

    Thumbnail code is pretty and useful

  • @powerpcx86
    @powerpcx86 ปีที่แล้ว

    You are the most wonderful cpp dev i know on TH-cam, but when would you consider using rust as the ultimate cpp replacement ?

  • @Splntxx
    @Splntxx ปีที่แล้ว

    I know this is a bit offtopic for your normal videos, but could you make a video about shaderdebugging on windows? I can follow your explainations really good and I am struggleing with this topic at the moment :) great video btw!

  • @bva0
    @bva0 ปีที่แล้ว

    Great video Cherno! I have a question regarding the implementation of your example of a contiguous vector of structures of position (pos) + velocity (ves) of each bird. Let's say that this vector is called pos_vel_vec. Now let's say you have to dynamically kill existing birds and add new birds, lots of times. How do you reutilize the positions of killed birds in the vector efficiently? Like, maybe set the velocity of a kill bird to zero then add the index of this killed bird in the array to a queue, which is then utilized to create new birds? If the queue is empty, use pos_vel_arr.push_back(). Main drawback is that you perform unnecessary calculations (assuming we want to avoid branching with a boolean mask of live birds). Another drawback maybe would be having to use a boolean mask.

    • @AntonioNoack
      @AntonioNoack ปีที่แล้ว

      In this case, the order of birds doesn't matter. Therefore, the best solution is to remove the last bird (just size--), and copy it onto the dead bird (effectively a memcpy of the size of one instance).
      If you iterate over the birds and kill them conditionally, you also can have a read and a write pointer, and just increment the wrote pointer on alive birds.

    • @AntonioNoack
      @AntonioNoack ปีที่แล้ว

      *write (I'm using YT on my phone, it's horrible 😱)

  • @AmrHendawy-g5u
    @AmrHendawy-g5u ปีที่แล้ว +1

    What is the name for this color them because it is so good

    • @igorthelight
      @igorthelight ปีที่แล้ว

      Looks like Darcula most likely ;-)

    • @AmrHendawy-g5u
      @AmrHendawy-g5u ปีที่แล้ว

      @@igorthelight I know darcula, it is not it.

  • @kurt7020
    @kurt7020 ปีที่แล้ว

    We shouldn't iterate through them, we should use recursion and pure functions to allocate a completely new copy every time we change a property value. XD

  • @MrGeneralScar
    @MrGeneralScar ปีที่แล้ว

    Do you do LUA? I am always looking for better ways to do things, the problem is when I want to test code outside of a game I write it for (an addon), I have to change the code to standard LUA and then back again because the game apparently uses a different code base for LUA parsing to what is latest and greatest. They also have thier own functions that dont exist in normal LUA.

  • @HenryLoenwind
    @HenryLoenwind ปีที่แล้ว

    10:30 modulo 2? Why waste so many CPU cycles? "return !(x && 1);" is so much faster. Save two extra instructions in half the cases by having isOdd() instead, when isEven would need to have a "!" both inside and outside the call.
    (Although right-shifting into carry and then branching on carry would be even faster...but that cannot be put into a function.)
    14:30 My example is the old file drawer. If everything that you need for your work is in one file drawer within your reach, is that faster than when you have a huge warehouse of file drawers with everything spread out? The same is true for computer memory. If everything the CPU needs is in the cache (i.e. "in reach"), it is faster than when it has to fetch it from the RAM sticks on the other side of the motherboard.

    • @pwhqngl0evzeg7z37
      @pwhqngl0evzeg7z37 ปีที่แล้ว

      For isEven, you should just use mod. Any reasonable compiler will optimize this for you, and it's more readable than a manual optimization, which I guess may not even be best if the compiler can find a better optimization using a special opcode or something for checking mod2 specifically.

  • @m4rt_
    @m4rt_ ปีที่แล้ว +2

    I would like to see you actually rewriting it

  • @onemoremagistr
    @onemoremagistr ปีที่แล้ว

    Really great! Thank you!

  • @robertlever
    @robertlever ปีที่แล้ว

    i would realy apriciate an explenation on enteties and how to implement it just for educational purpuses dont neeed the code but a nice drawing of it :D

  • @thev01d12
    @thev01d12 ปีที่แล้ว +1

    Would love to see you refactor this into something more scalable and optimized.

  • @easyBob100
    @easyBob100 ปีที่แล้ว +1

    10:38 "mod 2 == 0" .....
    try for isOdd:
    return (number & 1);
    Faster to just AND the LSB and return it IIRC. (Note: been a while, might be 'wrong', but the idea is right) :)

    • @arcanium_walker
      @arcanium_walker ปีที่แล้ว

      Idea is right, but in the C# world this is return 1 (And the C# not convert automatically to a Boolean type. In C#: (number & 1) != 1 ). But in C++ context the solution is faster than mod by 2. (I think) :D I prefer this method in some cases.

    • @Lord2225
      @Lord2225 ปีที่แล้ว +4

      It isnt. Every optimizer out there will optimize mod 2 out to fastest possible expression for given hardwere and additionaly it is not guaranteed that &1 will be any faster, but for sure less readable.

    • @easyBob100
      @easyBob100 ปีที่แล้ว +1

      @@Lord2225 If you can't read basic boolean operations, maybe programming isn't for you. ;)
      Seriously though, compilers don't always get things right, especially for more complicated things, so knowing things like this can save you clock cycles. I get what you're saying though. :)

    • @easyBob100
      @easyBob100 ปีที่แล้ว +1

      @@arcanium_walker Yeah I wasn't sure, and I don't program in C# either. I just don't like putting the if inside the isOdd function when you know the user of the function is putting it inside their own if statement. :D

    • @Lord2225
      @Lord2225 ปีที่แล้ว

      ​@@easyBob100 Or it will add few. Early optimalizaton is source of all evil. These kinds of micro "optimalizations" come from very early days of C and Pascal when optimizer wasnt very versatile, together with other vestiges like declaring varibles before assigning them ect. Stop this. Write clean code.

  • @TheKinderNinja
    @TheKinderNinja ปีที่แล้ว

    10:20 You can check whether a number is even this way if(!(num&1)). It's much faster than division.

    • @zdspider6778
      @zdspider6778 ปีที่แล้ว

      if ((num % 2) == 0)
      // is even
      if ((num % 2) != 0)
      // is odd

    • @TheKinderNinja
      @TheKinderNinja ปีที่แล้ว

      @@zdspider6778 I know. I thought the bitwise and operation would by faster. I just tested it. It turns out it's not actually faster on my computer.

    • @user-zu1ix3yq2w
      @user-zu1ix3yq2w ปีที่แล้ว

      @@TheKinderNinja is that due to compiler optimizations?

    • @TheKinderNinja
      @TheKinderNinja ปีที่แล้ว

      @@user-zu1ix3yq2w idk I tested it setting the compiler to "Debug", so it's likely not the optimisation. I should test it in assembly.

  • @TheCodingHubYT
    @TheCodingHubYT ปีที่แล้ว

    Great video!

  • @Keltheran
    @Keltheran ปีที่แล้ว

    For the even number check I prefer
    return !(number & 1);
    and yes, it is just to annoy people who reads it 🙂
    it is also probably the lowest amount of CPU instructions for the problem, though I do believe the compiler will change the mod into it (have not checked that though).

    • @hbirler
      @hbirler ปีที่แล้ว

      GCC actually generates ((~number) & 1) for either code in order to perfectly generate the values 0 or 1 without having to "cast" (number & 1) to boolean. (And ((~number) & 1) is definitely faster than branching, especially since in this case the branch would likely be unpredictable.)

    • @Keltheran
      @Keltheran ปีที่แล้ว

      @@hbirler And that is why you should almost always trust the compiler.
      My example didn't have any branches though, "! int" is branch-less since it uses the zero flag to set the resulting value, it uses more instructions than the bit flip though so the compiler wins again.
      Although with branching you might mean the if/else stack?

  • @DarthJane
    @DarthJane ปีที่แล้ว

    An inheritance based system is bad in a vector anyway, as it needs 2 redirections. For example you have classes A and B where B inherits from A both shoved into a vector it would first get an object which tells the computer which of the two it actually is with another pointer to the actual object. Otherwise it would need to either allocate enough space to hold the biggest object, which is very wasteful, and doesn't work well with precompilation and libraries, or override parts of objects, which would cause a lot of those being junk.

  • @mahfuzkabir7812
    @mahfuzkabir7812 ปีที่แล้ว

    Please do a video on actually implementing your changes!

  • @oleksiistri8429
    @oleksiistri8429 ปีที่แล้ว

    9:50 actually, i have such code in my projects, lol, maybe not with even/odd and true/false, but a lot of ifs comparing with number somewhere up to 35 )))

  • @akbarisroilov1002
    @akbarisroilov1002 ปีที่แล้ว +1

    Hey Cherno

  • @electronlabs2802
    @electronlabs2802 ปีที่แล้ว

    So lets say birds are inherited from Abstract bird... And there is a method that only exist on black birds .. you made collection of abstract birds and you lost the child type .. how would you implement the dispatcher without type check and down casting

  • @useronuralp
    @useronuralp ปีที่แล้ว

    Great vid as always Yan

  • @rafa_br34
    @rafa_br34 ปีที่แล้ว

    Great video as always!

  • @EraYaN
    @EraYaN ปีที่แล้ว

    Removing the jumps between the multiple vectors in memory and replacing them with virtual function lookups might still not be that great with this low amount of entity types.

  • @Simple_Simon_UK
    @Simple_Simon_UK ปีที่แล้ว +1

    Write the code to improve. Much more useful.

  • @usernamechefunziona373
    @usernamechefunziona373 2 หลายเดือนก่อน

    3:20 How do you do that black magic?

  • @FlotzOnYou
    @FlotzOnYou ปีที่แล้ว

    The "IsEven" function is priceless

  • @mrcrackerist
    @mrcrackerist ปีที่แล้ว +3

    x % 2 == 0 would be slower then x & 1, but this would deepened on the compiler optimizing or not optimizing.
    Anyways as always a nice video :)

    • @CD4017BE
      @CD4017BE ปีที่แล้ว +2

      In most programming languages (including C++) the result of the % operator has the same sign as the first argument. This means that if x < 0 then the x % 2 operation may produce a different result than x & 1 so the compiler can only optimize it if it can statically prove that x is never negative.

  • @Manas-co8wl
    @Manas-co8wl ปีที่แล้ว

    Hey Cherno. Y’have no idea the journey I went through. It was like an Alice in Wonderland journey trying to find a new language: Python, js, rust, Nim, julia, lua, haxe… and guess what. I came back here to stay. Ultimately found them all lacking in one area so much. I might continue using Haxe because of it ability to transpile, but at this point I’m so frustrated that I want to make my own transpiler that writes to cpp and create automatic bindings for higher languages. Like at this point that seems to be the way.
    Anyway.. hi. How was LD53? Came back to stay. Needed someplace to rant and I don’t know why I chose here but we’re back to cpp. Man finding a good language is so hard..

    • @phitc4242
      @phitc4242 ปีที่แล้ว

      do one thing, but do it right :D

  • @chiragsawajiyani8540
    @chiragsawajiyani8540 ปีที่แล้ว

    It will be helpful

  • @meyou578
    @meyou578 ปีที่แล้ว

    can you make tutorial of how to implement language server protocol

  • @Luke-nj8pf
    @Luke-nj8pf ปีที่แล้ว

    Can you do a developer react video talking about tears of the kingdom’s engine ?

  • @ThePowerRanger
    @ThePowerRanger ปีที่แล้ว

    I love these videos.

  • @trevthea5781
    @trevthea5781 ปีที่แล้ว +8

    Looking forward to more chat gpt code reviews.

    • @igorthelight
      @igorthelight ปีที่แล้ว

      Especially ChatGPT Plus (based on much more "smart" GPT-4) ;-)

  • @DarthJane
    @DarthJane ปีที่แล้ว

    I don't get why IsOdd should use modulus, it's an int, so just do 'return value & 1'. Way faster, and still obvious (I'd actually claim more obvious than using modulus is)

    • @pwhqngl0evzeg7z37
      @pwhqngl0evzeg7z37 ปีที่แล้ว

      Probably not more obvious, since there's probably more programmers who understand remainders than those who understand integer representation. And it'a definitely not faster unless you compile with -O0