Тёмный

The Importance of Scalable Code // Code Review 

The Cherno
Подписаться 644 тыс.
Просмотров 134 тыс.
50% 1

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.

Опубликовано:

 

30 июн 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 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 Год назад
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 Год назад
this
@ultimatesoup
@ultimatesoup 10 месяцев назад
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
@Squirrelies1 Год назад
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.
@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
@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 11 месяцев назад
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 11 месяцев назад
@@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 10 месяцев назад
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.
@user-lz1yb6qk3f
@user-lz1yb6qk3f Год назад
I would love to see this code actually modified using your recommendations.
@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!
@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 Год назад
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 2 месяца назад
You should use inheritance here if you want to do it in a more C++ way.
@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
@HenryLoenwind
@HenryLoenwind Год назад
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.
@Domix-nh8ws
@Domix-nh8ws Год назад
Please rewrite it with an ECS, or something similar it would be amazing to see the comparison.
@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)
@Satook
@Satook Год назад
Seeing it done is always helpful. I think watching each tweak and how is actually really important.
@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
@darkthunder301 Год назад
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.
@aj-jc4cv
@aj-jc4cv Год назад
Entity component system rewrite would be super useful. These videos are gold.🏅
@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
@Turalcar
@Turalcar 17 дней назад
@@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.
@scriptles
@scriptles Год назад
I love your video's, excellent work as usual. Keep up the good work teaching us.
@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 Год назад
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 10 месяцев назад
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.
@Asto508
@Asto508 10 месяцев назад
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.
@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
@literallyfiction
@literallyfiction Год назад
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.
@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.
@larryd9577
@larryd9577 11 месяцев назад
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.
@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!
@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!
@designator7402
@designator7402 Год назад
0 does fulfill all requirements of being an even integer, so yes, 0 is considered even in most circumstances.
@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 Год назад
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.
@maximalgamingnl9954
@maximalgamingnl9954 Год назад
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?
@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?
@megak550
@megak550 Год назад
Hello, can someone explain why the nesting is done? I mean std::vector.
@machimanta
@machimanta 11 месяцев назад
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
@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.
@avtem
@avtem Год назад
13:00 lmao, it made my day edit: please keep talking about memory it's really interesting
@onemoremagistr
@onemoremagistr Год назад
Really great! Thank you!
@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.
@useronuralp
@useronuralp Год назад
Great vid as always Yan
@powerpcx86
@powerpcx86 Год назад
You are the most wonderful cpp dev i know on RU-vid, but when would you consider using rust as the ultimate cpp replacement ?
@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!
@amoldhamale3202
@amoldhamale3202 Год назад
We need a dedicated video on cache hits and misses analysis
@maverikmiller6746
@maverikmiller6746 Год назад
This was pretty good. Thanks Chernoman.
@NotMarkKnopfler
@NotMarkKnopfler 11 месяцев назад
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! 👍
@Bbdu75yg
@Bbdu75yg Год назад
That thumbnail was so funny!😂
@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).
@pederslothzuricho7685
@pederslothzuricho7685 9 месяцев назад
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.
@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
@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.
@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 😱)
@TheCodingHubYT
@TheCodingHubYT Год назад
Great video!
@tambow44
@tambow44 11 месяцев назад
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.
@ThePowerRanger
@ThePowerRanger Год назад
I love these videos.
@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.
@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!
@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.
@MasterHigure
@MasterHigure Год назад
"hey what's up guys my name is China welcome back to code review Series" Auto-generated captions for the win.
@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
@paulfrischknecht3999
@paulfrischknecht3999 Год назад
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
@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.
@roboterbasteln
@roboterbasteln Год назад
0 is an even number. But in C++, unlike some other languages like Python, modulo for negative numbers returns negative remainders.
@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?
@stephanweinberger
@stephanweinberger 10 месяцев назад
@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.
@brunosilva-ed4pz
@brunosilva-ed4pz Год назад
13:16 Some big game devs should learn more about memory... (coff coff Hogwards Legacy coff coff)
@MrGeneralScar
@MrGeneralScar 10 месяцев назад
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.
@ladymushroom9485
@ladymushroom9485 4 месяца назад
10:00 if else is to slow for use cases like these. Optimize with a switch statement.
@meyou578
@meyou578 Год назад
can you make tutorial of how to implement language server protocol
@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
@augnix888
@augnix888 Год назад
Nice video
@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.
@FlotzOnYou
@FlotzOnYou Год назад
The "IsEven" function is priceless
@kurt7020
@kurt7020 9 месяцев назад
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
@oleksiistri8429
@oleksiistri8429 11 месяцев назад
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 )))
@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.
@m4rt_
@m4rt_ Год назад
I would like to see you actually rewriting it
@mahfuzkabir7812
@mahfuzkabir7812 Год назад
Please do a video on actually implementing your changes!
@wjrasmussen666
@wjrasmussen666 Год назад
Hey Cherno!
@gianbattistavivolo7449
@gianbattistavivolo7449 Год назад
What's your visual studio theme?
@igorthelight
@igorthelight Год назад
Looks like Darcula but I may be wrong
@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.
@akbarisroilov1002
@akbarisroilov1002 Год назад
Hey Cherno
@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.
@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 11 месяцев назад
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.
@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
@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.
@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.
@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.
@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.
@Lemon-lp1qb
@Lemon-lp1qb Год назад
The thumbnail got me laughing and traumatized at the same time.
@Necessarius
@Necessarius Год назад
Thumbnail code is pretty and useful
@draconicepic4124
@draconicepic4124 Год назад
The first thing I thought when I saw the code was: the Instruction Cache isn't happy.
@igorthelight
@igorthelight Год назад
Every newer CPU has more cache! Programmers: You underestimate my code-monkey powers! ;-)
@chiragsawajiyani8540
@chiragsawajiyani8540 Год назад
It will be helpful
@acelyon5221
@acelyon5221 Год назад
Ngl I hate seeing repeated code, I end up finding myself making some kind of repeated code and eventually it bothers me and I have to rewrite and try to make it better.
@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 11 месяцев назад
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
@bryannguyen1260
@bryannguyen1260 Год назад
That thumbnail instantly reminded me of Yanderedev. On a real note, this is important because in games like GTA V which is a huge example of scope/feature creep, you want to make it modular in case if you want to add features long term.
@Luke-nj8pf
@Luke-nj8pf Год назад
Can you do a developer react video talking about tears of the kingdom’s engine ?
@cpp_medium_rare3474
@cpp_medium_rare3474 Год назад
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.
@REktSigMa
@REktSigMa Год назад
LOL This could be a complete data base of the element "Bird_Types" LOL
Далее
SOME UNIQUE C++ CODE! // Pacman Clone Code Review
26:42
All about MEMORY // Code Review
33:42
Просмотров 158 тыс.
skibidi toilet multiverse 039 (part 1)
05:29
Просмотров 5 млн
Weak Pointers in C++ (std::weak_ptr)
17:25
Просмотров 24 тыс.
How Senior Programmers ACTUALLY Write Code
13:37
Просмотров 1,4 млн
Harder Than It Seems? 5 Minute Timer in C++
20:10
Просмотров 149 тыс.
Never install locally
5:45
Просмотров 1,7 млн
Pong Clone in C++ // Code Review
34:31
Просмотров 94 тыс.
Naming Things in Code
7:25
Просмотров 2 млн
What does larger scale software development look like?
24:15
how NASA writes space-proof code
6:03
Просмотров 2,1 млн
How principled coders outperform the competition
11:11