The Importance of Scalable Code // Code Review

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!
Patreon ► / thecherno
Instagram ► / thecherno
Twitter ► / thecherno
Discord ► / discord
CODE ► github.com/MariuszDot/Game_Fl...
📚 CHAPTERS
0:00 - Recap
0:55 - Analyzing repeated code
9:38 - Memelord Polymars
12:43 - Performance and scaling code
27:16 - Entity Component System (ECS)
Send an email to chernoreview@gmail.com with your source code, a brief explanation, and what you need help with/want me to review and you could be in the next episode of my Code Review series! Also let me know if you would like to remain anonymous.
Hazel ► hazelengine.com
🕹️ Play our latest game FREE (made in Hazel!) ► studiocherno.itch.io/saving-c...
🌏 Need web hosting? ► hostinger.com/cherno
💰 Links to stuff I use:
⌨ Keyboard ► geni.us/T2J7
🐭 Mouse ► geni.us/BuY7
💻 Monitors ► geni.us/wZFSwSK
This video is sponsored by Brilliant.

Пікірлер: 236

  • @TheCherno
    @TheCherno Жыл бұрын

    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

    11 ай бұрын

    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 Жыл бұрын

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

  • @hourglass2836

    @hourglass2836

    11 ай бұрын

    this

  • @ultimatesoup

    @ultimatesoup

    8 ай бұрын

    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

  • @CatzHoek
    @CatzHoek Жыл бұрын

    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 Жыл бұрын

    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

    Жыл бұрын

    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

    Жыл бұрын

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

    Жыл бұрын

    It's missing the "- resilient code"

  • @Dr-Zed

    @Dr-Zed

    Жыл бұрын

    ​@@rafa_br34 updated the list

  • @peezieforestem5078

    @peezieforestem5078

    Жыл бұрын

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

  • @Squirrelies1
    @Squirrelies111 ай бұрын

    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 Жыл бұрын

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

  • @Mini_CS

    @Mini_CS

    10 ай бұрын

    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

    10 ай бұрын

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

    8 ай бұрын

    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 Жыл бұрын

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

  • @BulletproofOutlaws
    @BulletproofOutlaws Жыл бұрын

    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

  • @user-lz1yb6qk3f
    @user-lz1yb6qk3f Жыл бұрын

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

  • @Satook
    @Satook Жыл бұрын

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

  • @urugulu1656
    @urugulu1656 Жыл бұрын

    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

    Жыл бұрын

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

  • @legitjimmyjaylight8409

    @legitjimmyjaylight8409

    11 ай бұрын

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

  • @soniablanche5672

    @soniablanche5672

    10 ай бұрын

    or just put the score as a property of bird

  • @yiranmushroom

    @yiranmushroom

    15 күн бұрын

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

  • @Treborbobuk
    @Treborbobuk Жыл бұрын

    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!

  • @Domix-nh8ws
    @Domix-nh8ws Жыл бұрын

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

  • @fyvefouroh
    @fyvefouroh Жыл бұрын

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

  • @amoldhamale3202

    @amoldhamale3202

    Жыл бұрын

    I agree

  • @APaleDot
    @APaleDot Жыл бұрын

    > 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 Жыл бұрын

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

  • @HenryLoenwind
    @HenryLoenwind11 ай бұрын

    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.

  • @omarmagdy1075
    @omarmagdy1075 Жыл бұрын

    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.

  • @darkthunder301
    @darkthunder30110 ай бұрын

    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.

  • @m4rt_
    @m4rt_ Жыл бұрын

    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

    Жыл бұрын

    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

    Жыл бұрын

    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

  • @scriptles
    @scriptles Жыл бұрын

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

  • @Asto508
    @Asto5088 ай бұрын

    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.

  • @MrHaggyy
    @MrHaggyy8 ай бұрын

    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.

  • @avtem
    @avtem Жыл бұрын

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

  • @useronuralp
    @useronuralp Жыл бұрын

    Great vid as always Yan

  • @rafa_br34
    @rafa_br34 Жыл бұрын

    Great video as always!

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

  • @StevenMartinGuitar
    @StevenMartinGuitar Жыл бұрын

    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

  • @larryd9577
    @larryd95779 ай бұрын

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

  • @literallyfiction
    @literallyfiction Жыл бұрын

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

  • @jamesmnguyen

    @jamesmnguyen

    11 ай бұрын

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

  • @xeridea
    @xeridea Жыл бұрын

    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

    10 ай бұрын

    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.

  • @maverikmiller6746
    @maverikmiller6746 Жыл бұрын

    This was pretty good. Thanks Chernoman.

  • @maximalgamingnl9954
    @maximalgamingnl995411 ай бұрын

    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?

  • @Bbdu75yg
    @Bbdu75yg Жыл бұрын

    That thumbnail was so funny!😂

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

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

  • @onemoremagistr
    @onemoremagistr Жыл бұрын

    Really great! Thank you!

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

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

  • @designator7402
    @designator7402 Жыл бұрын

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

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

  • @amoldhamale3202
    @amoldhamale3202 Жыл бұрын

    We need a dedicated video on cache hits and misses analysis

  • @NotMarkKnopfler
    @NotMarkKnopfler9 ай бұрын

    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! 👍

  • @megak550
    @megak55011 ай бұрын

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

  • @machimanta

    @machimanta

    10 ай бұрын

    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

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

  • @powerpcx86
    @powerpcx86 Жыл бұрын

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

  • @MrGeneralScar
    @MrGeneralScar9 ай бұрын

    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.

  • @TheCodingHubYT
    @TheCodingHubYT Жыл бұрын

    Great video!

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

  • @ThePowerRanger
    @ThePowerRanger Жыл бұрын

    I love these videos.

  • @meyou578
    @meyou578 Жыл бұрын

    can you make tutorial of how to implement language server protocol

  • @danielbaulig
    @danielbaulig Жыл бұрын

    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

    10 ай бұрын

    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.

  • @ladymushroom9485
    @ladymushroom94853 ай бұрын

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

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

  • @shadeblackwolf1508
    @shadeblackwolf150811 ай бұрын

    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

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

    11 ай бұрын

    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

    11 ай бұрын

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

  • @Stabby666
    @Stabby666 Жыл бұрын

    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!

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

  • @jakeoshay
    @jakeoshay11 ай бұрын

    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.

  • @FlotzOnYou
    @FlotzOnYou Жыл бұрын

    The "IsEven" function is priceless

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

  • @tambow44
    @tambow4410 ай бұрын

    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.

  • @brunosilva-ed4pz
    @brunosilva-ed4pz Жыл бұрын

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

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

  • @augnix888
    @augnix888 Жыл бұрын

    Nice video

  • @pederslothzuricho7685
    @pederslothzuricho76857 ай бұрын

    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.

  • @JohnSmith-ze7sv
    @JohnSmith-ze7sv11 ай бұрын

    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.

  • @paulfrischknecht3999
    @paulfrischknecht399911 ай бұрын

    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

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

  • @lennuard_6998
    @lennuard_6998 Жыл бұрын

    does it has to do something with graphics or can i submit something nongraphical (is this a word?) ?

  • @atijohn8135

    @atijohn8135

    Жыл бұрын

    transmit your c++ code in morse code through audio files 👍

  • @lennuard_6998

    @lennuard_6998

    Жыл бұрын

    @@atijohn8135 ill do, thanks!

  • @not_ever

    @not_ever

    Жыл бұрын

    If you look at the other projects that have been code reviewed you might find some non-gui or non-graphics based applications. What's probably most important comes with a good README and actually compiles on the Cherno's computer.

  • @MasterHigure
    @MasterHigure10 ай бұрын

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

  • @oleksiistri8429
    @oleksiistri84299 ай бұрын

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

  • @coldblush7201
    @coldblush7201 Жыл бұрын

    Im bad at C++ so can someone please explain why code author using vector instead of doing vector ? Or it simply doesn't work like that? Would that make any difference?

  • @HanayouDev

    @HanayouDev

    Жыл бұрын

    some of the main advantages to creating pointers to classes/structs over creating them directly: - The value a pointer 'points' to is initilised by using the new/delete, meaning the memory allocated for that type is created on the heap rather than the stack. - Passing around pointers is far more lightweight and convenient than passing around or copying entire classes (typically only a 32-bit memory address instead of an entire class or struct). - Polymorphism

  • @MrPoselsky

    @MrPoselsky

    Жыл бұрын

    ​@@HanayouDev Ok, what you wrote leaves more questions than answers and just throwing word polymorphism out of nowhere is very confusing. To answer simply it's just because of memory. On modern x86-64 cpu pointer is size of 4bytes, while class can have many member variables which also take memory. So vector takes already existing objects whereas vector would need to copy the class over to vector and that would mean also copying member variables which can take significantly more memory.

  • @HanayouDev

    @HanayouDev

    Жыл бұрын

    @@MrPoselsky Appreciate you detailing the points I made more (though they were are the same points, just in more words), I just didn't really have the time to write a super in-depth answer, and bluntly I think to understand the benefit/value of what either of us have written requires commitment to go and read up about C++ generally anyway. I could probably try to summarise polymorphism, but for someone w/o experience I don't think a short YT comment with no visual aids is going to be massively helpful regardless (probably just more confusing if anything). Probably best for them to see it then if they care enough, get curious and investigate it further themselves.

  • @RMDragon3

    @RMDragon3

    Жыл бұрын

    You can have a vector but it can lead to some issues or more inefficient code. For example, if you add more elements than the space currently reserved, the program will need to allocate a new, bigger space and copy all the existing elements there. This is (generally) less efficient with actual classes than pointers. It also forces you to create the code to make a copy of the actual class, which is not always straight forward. It's basically due to the fact that C++ provides low-level access to memory, allowing you to really control how everything is represented there but also forcing you to explicitly say each time. I believe most other languages use approaches similar to the pointers for vectors/lists, but they are made invisible to users for ease of use.

  • @anon1963

    @anon1963

    Жыл бұрын

    @@MrPoselsky vector stores it's data on the heap anyway, regardless if it's a vector of pointers or objects, so you are storing the same amount of memory. do you think a class that is 100 bytes in size is magically reduced to 4 bytes when it's allocated on the heap(new Class)? no.

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

  • @chiragsawajiyani8540
    @chiragsawajiyani8540 Жыл бұрын

    It will be helpful

  • @easyBob100
    @easyBob100 Жыл бұрын

    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

    Жыл бұрын

    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

    Жыл бұрын

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

    Жыл бұрын

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

  • @HenryLoenwind
    @HenryLoenwind11 ай бұрын

    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

    9 ай бұрын

    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.

  • @wjrasmussen666
    @wjrasmussen666 Жыл бұрын

    Hey Cherno!

  • @user-pc5ss2vr4e
    @user-pc5ss2vr4e Жыл бұрын

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

  • @igorthelight

    @igorthelight

    Жыл бұрын

    Looks like Darcula most likely ;-)

  • @user-pc5ss2vr4e

    @user-pc5ss2vr4e

    Жыл бұрын

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

  • @m4rt_
    @m4rt_ Жыл бұрын

    I would like to see you actually rewriting it

  • @mahfuzkabir7812
    @mahfuzkabir7812 Жыл бұрын

    Please do a video on actually implementing your changes!

  • @trevthea5781
    @trevthea5781 Жыл бұрын

    Looking forward to more chat gpt code reviews.

  • @igorthelight

    @igorthelight

    Жыл бұрын

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

  • @gianbattistavivolo7449
    @gianbattistavivolo7449 Жыл бұрын

    What's your visual studio theme?

  • @igorthelight

    @igorthelight

    Жыл бұрын

    Looks like Darcula but I may be wrong

  • @kurt7020
    @kurt70207 ай бұрын

    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

  • @roboterbasteln
    @roboterbasteln10 ай бұрын

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

  • @akbarisroilov1002
    @akbarisroilov1002 Жыл бұрын

    Hey Cherno

  • @stephanweinberger
    @stephanweinberger9 ай бұрын

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

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

    11 ай бұрын

    do one thing, but do it right :D

  • @Necessarius
    @Necessarius11 ай бұрын

    Thumbnail code is pretty and useful

  • @thev01d12
    @thev01d12 Жыл бұрын

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

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

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

  • @Lemon-lp1qb
    @Lemon-lp1qb Жыл бұрын

    The thumbnail got me laughing and traumatized at the same time.

  • @mrcrackerist
    @mrcrackerist Жыл бұрын

    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

    Жыл бұрын

    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.

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

  • @oguzhantopaloglu9442
    @oguzhantopaloglu9442 Жыл бұрын

    bro puts a brilliant ad but doesnt know that zero is even 💀

  • @mohammadyaghini1237
    @mohammadyaghini1237 Жыл бұрын

    Keep it DRY

  • @Luke-nj8pf
    @Luke-nj8pf Жыл бұрын

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

  • @dt1926
    @dt1926 Жыл бұрын

    That sounds like good content to me, please do.

  • @andresvallelisboa5511
    @andresvallelisboa5511 Жыл бұрын

    12:30 I cannot stop laughing