Practical Optimizations

Поділитися
Вставка
  • Опубліковано 17 лис 2024

КОМЕНТАРІ • 121

  • @sanderbos4243
    @sanderbos4243 Рік тому +14

    36:25 "Optimization is a feature: it's giving you the ability to have other features."
    I'm stealing that one :-)

  • @raspofabs
    @raspofabs Рік тому +69

    That's not Mike, that's me! Nicely presented talk. I am so glad to see people sharing this knowledge in all the different forms.

    • @slipster216
      @slipster216  Рік тому +18

      Doh! I searched for Mike Acton on images (as you do) and your icon came up - the side eye nature of it was too good not to use..

    • @slipster216
      @slipster216  Рік тому +19

      You know I kind of want to go back and dub "Richard Fabian" into it with a clearly overdubbed voice, but I'm both too lazy and don't think anyone would get the joke.

    • @Tottelbe
      @Tottelbe 2 місяці тому

      I watched Mike Acton's talk (many times) and also read your book on Data Oriented Design (Many times. Very helpful book, by the way!).
      Your picture came up during this video and I recognized it but couldn't place it. Jason mentioned Mike, but that did not feel right.
      Now that I saw your comment it all makes sense. :D

  • @Hassanali-p7w4f
    @Hassanali-p7w4f 7 місяців тому +2

    One of many amazing things i understood in unity, as i am just a beginner in unity with almost like 9 months of personal work using only monobehaviour , but always thought how can we make like 500,000 things in a simple computer or laptop that has its only built in GPU to delegate tasks to but this practical work of code is just so much better then anything i'v learned yet thanks Jason, need more of this type of videos from Expert Seniors like yourself.
    do take time to teach things like this in a simple series of videos just targeting simple but not used right concepts as many beginners just never know that even code could be optimized in unity and in any engine.

  • @kallehed6330
    @kallehed6330 Рік тому +8

    "Don't write a rocket class, write a rocket manager" Holy molly, this changes everything

  • @anlcangulkaya6244
    @anlcangulkaya6244 Рік тому +12

    2:44 Mike Acton's shirt hahahaha

  • @henrykkaufman1488
    @henrykkaufman1488 13 днів тому

    Wonderful Mike Acton famous presentation reference using the shirt. 🙂

  • @baroquedub
    @baroquedub Рік тому +37

    Pure gold. I feel very privileged to finally get to hear one of your talks. It was well worth the wait, you're a great teacher. Thank you

  • @boxtodragon
    @boxtodragon Рік тому +18

    This video is educational it talks about DOD in a very precise way with examples that we can all get behind on. I applaud Jason for sharing his experience and knowledge in this field as very little is available on UA-cam that actually talk about the topics involved in the video.

  • @AntonHand
    @AntonHand Рік тому +16

    Super valuable talk Jason. Thank you so much for this. It was the beating over the head I needed.

  • @jertlemiah
    @jertlemiah Рік тому +3

    This was super interesting, I like the way you've structured your talk with examples of increasing fidelity, it paves the way for everything to connect and make sense

  • @unbeGames
    @unbeGames Рік тому +4

    Fantastic talk! I had a similar task to make a planetary terrain for the game called Rocket Science. The only catch was that it should be Earth scale. The first attempt to make it "usual way" lead me to 10 FPS with no room to optimize. Then I sat down, reasoned about the data, rewrote everything using Jobs and Burst as described in the video, and now I generate Earth-like planets in less than 1 ms.

  • @NeatWolf
    @NeatWolf Рік тому +4

    Thanks for the talk Jason! I think recruiters and SOLID principles fanatics are going to turn up the nose a lot to this - especially during an interview. But. That's where experience goes beyond every other possible academization of the design process.
    I'll try to make treasure of this, whenever applicable. A sincere thank you for sharing.

  • @JakeBirkett
    @JakeBirkett Рік тому +3

    As someone who used to code in assembly on a C64 and Amiga where optimisation mattered, this talk was really great! Fascinating thanks.

  • @92Garrus
    @92Garrus Рік тому +1

    This is excellent, Jason! Thanks a lot for uploading. This is organized similarly to the Molly Rocket and Unity ECS talks I've listened to, but you present a lot more hands-on and practical supplemental info which drives the point home a lot better than anyone else I've seen.

  • @TurboMakesGames
    @TurboMakesGames Рік тому +4

    Awesome talk, really appreciated the practical implementations of data-oriented design.
    Also loved that bit of wisdom at the end of "don't practice mediocrity."

  • @RecOgMission
    @RecOgMission 3 місяці тому

    Hi Jason. I've seen a few of your MicroSplat videos in the last few months, and just watched this one. I just wanted to say: You are a true artist and a genius, and present the subject matter so clearly! Thanks for your contributions - this is immensely interesting and useful!
    I've been working on a complex terrain shader for a while, and how nice to find that some of the stuff I did there aligns with your advice in the terrain shader section :)

  • @chosencode5881
    @chosencode5881 Рік тому +2

    I cannot thank you enough for posting this! You are a legend of this industry, I will be buying your assets from the Unity Store at full price

  • @RedOrav
    @RedOrav Рік тому +1

    Gotta love how you present all these incredibly valuable gold nuggets of performance from the comfort of your hammock. The only thing I would point out is that in 51:00 you compare array of structure vs array of class whereas I think you meant array of structure vs structure of array, just putting it here in case someone is curious and wants to look it up

  • @recondeveloper2023
    @recondeveloper2023 Рік тому +1

    Nice presentation Jason, well thought out.

  • @sv_gravity
    @sv_gravity Рік тому

    After 16:00 in the talk it has gone to a much less comprehensible hints and without code examples, but still good and we appreciate it. Thank you.

  • @ErikBorchersVR
    @ErikBorchersVR Рік тому +3

    Thank you for posting this talk Jason. I'm working on getting a large dense forest to run on Quest 2. You've given me a lot to think about and work with.

  • @gamingyourway
    @gamingyourway 10 місяців тому +1

    That was excellent, thank you so much for sharing this.

  • @dreamisover9813
    @dreamisover9813 Рік тому +1

    Awesome to see a talk about this topic from you! Have been looking into data oriented design in the past, but I haven't really been paying much attention to it in my recent projects.

  • @MisterKidX
    @MisterKidX Рік тому +1

    Amazing talk, so much info in so little time. We demand more!

  • @harmonite99
    @harmonite99 Рік тому +1

    Thank you so much for making this video and explaining the concepts super clear and simple.

  • @2Jackrabbit
    @2Jackrabbit Рік тому +1

    You've always been a reference and a master, thanks sooo much for sharing all this so we can learn from the master.

  • @MihaiDesigns
    @MihaiDesigns Рік тому +1

    Amazing presentation, thank you!

  • @BartWronsk
    @BartWronsk Рік тому +11

    Great talk - I loved the practical, real-life examples and the non-rant, well-reasoned tone (as opposed to some proponents of DoD).
    I think your talk is super useful to show to people who just graduated from college (or are not formally educated, just start programming) to show how "innocent" design choices impact performance greatly.
    I would like to pushback a little bit, however, on the flexibility of such designs and performance as a "default" and allowing features - stemming from my own experience.
    I agree that fast performance gives a budget for many new interesting features and effects, but "systems" style design can also limit other types of innovation.
    I was an engine and graphics programmer on Witcher 2, then lead programmer on Witcher 2 Enhanced Edition, our port to X360 and the first time studio has shipped any console game.
    Our engine was "anti-pattern" when it comes to high-performance design.
    Individual entities, individual components, individual update - and everything scriptable, every single component in their update can find any other component of another object (with various, 100% "global" access systems by names, paths, tags!) and do "anything" to them through scripts.
    Sounds horrible? Yes, it was slow - and error-prone.
    But I'd argue that without it, we wouldn't have shipped AAA game with 10 programmers on average (engine, tools, graphics, and game - this is in total!) and a total team size of ~70 people.
    We just couldn't write all the systems necessary for a large-scale RPG full of custom quests and relied on quest designers - who were scripting the game and many systems as they needed.
    Such flexibility also allowed them to do crazy creative and story-driven quests, unlike anything in a video game before.
    For the X360 version we obviously "systemified" many things - like a system for background NPCs, foliage, making many things not-objects.
    And I tend to think that, in many cases, this is the right model.
    Initially - allow for extreme creativity and flexibility, reduce dependencies of other teams on programmers.
    Then find out the actual scale and amount of things and create systems out of those, optimizing common use cases afterward.
    Just like "future programming" and making things overly abstract and general is a design error (I agree with your point here), to me, writing systems assuming there "might" be 100s of thousands of objects (when, in reality, there are just a few) is the same type of fallacy.
    And it obviously depends on the needs. One designs systems for a shooter very differently than for a narrative RPG full of custom quests (instead of cookie-cutter systemic ones, like in older Ubisoft games).

    • @slipster216
      @slipster216  Рік тому +9

      I'm not arguing against that at all. For instance, having your player character controller being written to handle 1000s of characters is likely not going to pay off since it's used once - what you want is something that's fast to customize to handle all the random edge cases you run into. Great, the sequel means you have two of them for co-op, so what.
      But there are certainly areas where having a more general system with lots of ability to script/overload it is more useful than being fast - though even that you can see massive differences in performance based on how you write it IE: Inverting the virtual function call in the example in the video so it gets hit once per mesh instead of once per vertex - if you don't understand the difference there, your throwing away performance for absolutely no gain.
      The point is to write code for the context it's used in, not to always reach for the general abstraction layers people are taught in school, which is what I see constantly. In fact, most schools don't seem to teach a performant minded approach at all, so this is all people know. I see tons of code which is "well designed" by these standards but performs horribly because the coder writing it simply didn't think about or know how much cost the code they were writing was incurring. And as we move into higher and higher level languages and abstractions, people get further from needing to understand this stuff until you end up with a text editor that can't display text as fast as a user can type it, despite being run on a machine with 8 blazing fast processors.

    • @BartWronsk
      @BartWronsk Рік тому +2

      @@slipster216 I don't know why people keep bringing this text editor example, it's pretty bad faith IMO.
      This is NOT because of bad programming practices or programmers having no idea how to optimize things, but because of *product management* and priorities.
      Things get fixed until 99% (or some other percentage) of users are happy and don't see a problem - and the product managers decide it.
      I don't care if the text editor lags a bit; it does not bother me or change my productivity. Someone else might care - and that's ok; I understand it. But it's like this with 1000s of features - and, ultimately, someone decides which bugs will be fixed, which features will be shipped, and which performance metrics are worth optimizing.
      It was like this in business software, video games, and working at Google on camera algorithms. There's a budget and target for everything set by PMs (or equivalent stakeholders), and if something is under it, you work on other, higher-priority stuff.

    • @slipster216
      @slipster216  Рік тому +11

      @@BartWronsk While that sometimes the case, I've worked on teams where the code would never be that bad in the first place, and ones where optimization is done late stage and only when prioritized, and generally the former makes better software in my experience.
      My first game (Asheron's Call) used a cluster of 6 p133 quad core machines as a server for 2000+ concurrent players, in a full 3d world, with physics and everything being run on the server as well as the client. When I worked on f2p mobile games years later, a server for a game much simpler than that game (no 3d, no physics) took dozens of top end amazon instances to for the same amount of people.
      Now I buy the argument that sometimes throwing servers at the problem is a valid way to deal with it, but I don't buy the argument that writing optimal code is so much harder, less maintainable, or decreases productivity that you should just always write slow, crappy code. Most software today runs like crap, and it doesn't have to, and the schedule doesn't come into play if you simply write decent code to begin with. It's actually pretty easy to do that. I see a 16x speedup in my example without increasing its complexity, and would have written it that way to begin with, thus would have cost 0 time on the schedule.

  • @cfffba
    @cfffba Рік тому

    haha, Mike Acton's shirt got me in stitches 😂 I love these subtle jokes.

  • @cameronetto
    @cameronetto 9 місяців тому

    This is great! I love to see unique ways to use unity thats actually more optimal. "Optimization is a design time problem" Yes! Exactly! I absolutely despise the odea of "we'll fix it in an optimization pass"

  • @ashwanishahrawat4607
    @ashwanishahrawat4607 Рік тому

    Just got to know you last month, and I realized I'll spend next few years to go over your work and consume the knowledge you have shared with us.
    (actually wanted to say I felt some water in my eyes as soon as i saw you, i'm in office i should control myself)

  • @thietduy
    @thietduy Рік тому +2

    pure diamond!!! I always to learn from you sir 🥰😇

  • @alapidis
    @alapidis Рік тому +1

    Wow what a great presentation! Thank you!

  • @valentinstudio3334
    @valentinstudio3334 Рік тому +2

    Thank you so much for this, super useful, I was glad I could listen to someone who knows his stuff! Thanks!

  • @DonC876
    @DonC876 Рік тому +2

    This was immensely interesting and helpful! You are really good at presenting/teaching!
    Is it possible that you might do another one of these and/or share a reading list? I feel like especially with optimization, one has to piece information together from a lot of different sources, which often contain outdated, partially incorrect or even completely false information. In the end it often comes down to benchmarking the code in question but that can be pretty time consuming. So getting someone like you to share his findings and insights is absolutely invaluable! i am looking forward to read the rest of your blog posts and finally experiment with branching optimization in shaders.

  • @thFaust
    @thFaust Рік тому +1

    Great Overview, thanks for that, I love data oriented design. It is often times the answer to problems one might run into later on when building software.

  • @Tekay37
    @Tekay37 Рік тому +1

    Thank you for sharing this talk. I learned a lot from it (and it confirmed my understanding of DOD)! :D

  • @mezzanine510
    @mezzanine510 Рік тому +2

    Excellent stuff, thanks a lot for this overview.

  • @def0rp
    @def0rp Рік тому

    Great talk! And very inspiring and deep thought about "practicing mediocrity".

  • @バオバイバー
    @バオバイバー Рік тому +1

    Thank you for this video. As much as I love DOD, a lot of the books on it use (correct, but) very contrived examples. It's refreshing to hear about actual work done on actual games for once, even if it's fairly high level. I'd love to see a video on the GPU branching topic as well.

  • @tvanantwerp
    @tvanantwerp Рік тому

    This was a really fascinating talk! I mostly work on web stuff and don't often encounter these sort of problems. Or, perhaps, I encounter them all the time but we, the web community, consistently handle them badly. (It certainly feels that way, when simple websites are janky as hell but video games create immersive worlds at scale and speed.) I'm going to have to stop and think if there are ways to take these insights and apply them to my problems too.

  • @xarcaz
    @xarcaz 8 місяців тому

    Great video. One thing that would have been interesting to mention in the first example would be the option of utilizing domain knowledge and existence-based processing by redesigning it so that the arrays only contain elements where the stamina or health aren't at max capacity (which, at least for health, would be the common case and thus reduce the number of elements to process to a tiny fraction). Likewise, by keeping dead creatures out of it as well you'd eliminate the branching in the update function in regards to the upper and lower bounds, so it would just look like `hp = min( hp + hp_regen * dt, max_hp );`.

    • @slipster216
      @slipster216  8 місяців тому +1

      I chose not to because then it becomes a video about array management, not “look how fast iterating over linear memory is”. You’ll notice I don’t really talk about how to get data into arrays via ECS like systems, etc.

    • @xarcaz
      @xarcaz 8 місяців тому

      @@slipster216 That's fair, good point. 👍

  • @Sam3DX
    @Sam3DX Рік тому +2

    Excellent talk, super valuable!

  • @favalon79
    @favalon79 Рік тому

    Very well presented! Showing real games examples is invaluable.

  • @anonymous49125
    @anonymous49125 8 місяців тому +3

    By and large I agree with this video. My only hot take to the contrary is: there is nothing wrong with writing slow code that is easy to read and maintain 99% of the time; in the instances where performance actually is an issue, then readability and 'will to live' be damned and then go ham (with some of the optimizations in this video, and so many more that are so much more insidious and evil in nature). Slow isn't a problem for the vast majority of things, so it isn't wise to build technical debt and mental strain into a project at an atomic level just to make it so everything is 'fast' (in regards to 44:05 ), because not everything needs to be fast it would be a waste of time and what you are trading it for is what you really actually need: for things to be easy to digest at a glance and be as least painful to work with as possible.

    • @slipster216
      @slipster216  8 місяців тому +3

      The idea that optimal code means it’s somehow harder to maintain or read is a false equivalency. Most of the changes done in this video actually make the code more clear, more maintainable, and much easier to reason about since it doesn’t have tons of framework and abstraction layers between it and the transform being performed to the data.

  • @mildsoup
    @mildsoup Рік тому +2

    Great talk, thanks for sharing

  • @nameno7032
    @nameno7032 6 місяців тому

    This talk is so good, i have to watch multiple times to get it into my head. Hope more content like this from you Jason
    Btw, if unity Mathf so slow, can you give a quick introduce to what you have done to make math operation faster?
    Thanks

  • @johnhio1843
    @johnhio1843 Рік тому +1

    Thanks for doing this again Jason. Also, love microverse.

  • @KhalilArafan
    @KhalilArafan 7 місяців тому

    Magnificent. Thank you.

  • @tychepi6576
    @tychepi6576 Рік тому +1

    Thank you for sharing 🙏

  • @mkjyt1
    @mkjyt1 6 місяців тому

    Best video I've seen this year

  • @antonymorsas
    @antonymorsas Рік тому

    This video its pure gold. Thanks!

  • @sniffdogg420
    @sniffdogg420 Рік тому +1

    thanks for rerecording this, Jason.

  • @KeithSwanger
    @KeithSwanger Рік тому

    Great talk, thanks for sharing!

  • @takeshiofficial7255
    @takeshiofficial7255 Рік тому +1

    Thank you very much 🫡

  • @edwardnewtonLA
    @edwardnewtonLA 4 місяці тому

    I enjoyed the daylights out of that, thank you. :)

  • @TheKiwiCoder
    @TheKiwiCoder Рік тому +2

    “If you just take a bunch of sh*t code and run it on multiple processors, all you’re doing is spreading sh*t around” 😂 Brilliant

  • @beardordie5308
    @beardordie5308 Рік тому

    🤯 Thank you for this

  • @christian-loock
    @christian-loock 7 місяців тому

    These theoratical examples at the beginning look very simple. The part I have a hard time wrapping my head around, is how you actually manage all those structs manually. In a GameObject you have everything neatly contained, and when you delete a GM, you destroy all the components on them aswell. I would be interested to see some actualy real world implementations of this design philosophy, to be able to wrap my hand around it better.

    • @slipster216
      @slipster216  6 місяців тому

      You can look up ECS systems like flecs and Unity's new ECS system. They are effectively databases for rapidly getting the data you need and accessing them in linear memory, without having to manage that data manually, as I do in this video (and often do as well in production code).

  • @pikuma
    @pikuma Рік тому

    Great talk. Thank you!

  • @while_coyote
    @while_coyote 10 місяців тому

    This was so useful.

  • @ddstar
    @ddstar Рік тому

    thanks jason. i understood all of that

  • @Nik-oe7df
    @Nik-oe7df 7 місяців тому

    Thank you so much, extremely helpful.
    Any thoughts on sparse sets in general, and for associating data between arrays using an id?

  • @mike998
    @mike998 Рік тому +7

    Thank you for this, optimization is one of my favorite things in gamedev so this helps me a lot 👍
    Link to the Walking Dead video btw : ua-cam.com/video/hUZbkqLRYus/v-deo.html

  • @JumpCatStudio102
    @JumpCatStudio102 Рік тому +2

    Thank you Jason. Can you expand your example for the monster data a bit more. What if the monster dies and we need to remove them from array, or add new monster in the array. How will the monster manager resolve around more complex case of computation? For example: monster physics movement, pathfinding, etc. I think these will help beginners like me a lot to have a good understanding of complex architecture.

    • @slipster216
      @slipster216  Рік тому +12

      The simplest way would be to use a List instead of an array. In C# list is slightly slower, but it's still continuous in memory you just pay a cost for resizing that sometimes. But when you're already dealing with a 216x speedup you can afford some overhead for connivence.
      You might also go the struct of array route where your monsterdata looks like:
      struct Monsters
      {
      NativeList health;
      NativeListstamina;
      NativeList alive;
      etc..
      }
      With this, you can write a job which gets passed the health and alive arrays for all monsters, thus only accessing that data and not all the data a monster has. Another job might use stamina and alive, etc. (You could also just use health == 0 for the alive state). Note that when something is 216 times faster, it's not that necessary to be ultra efficient about what's in the list either, so sometimes the answer is "who cares, just process them all anyway".
      If you're in Unity, you could also use ECS to compose your monster data from many different components (structs), and the entity system can act as a database to gather the data you need for each task and process them efficiently. For instance, you might have a struct with no data called "DeadState", and essentially write a query which gathers all MonsterData's without the dead state component and processes them. This is kind of like the example above, but you can add/remove components from things, write jobs which gather the data for you from any number of components on any entities, etc. For instance, in this model anything with the alive component and health component can be processed together, regardless of if it's a monster or a player or whatever. This is designed to get you closer to the "speed of light" on all operations.
      However, I will say that in most of the game I work on, I don't need to go this far. Usually they were already architectured around game objects not the ECS system, and enough bottlenecks are in obvious 'enclosed' systems that I can just do the simple versions. Basically, the complexity comes when you try to introduce this everywhere for everything. But if your working on a closed system where the data is known (ie: Planet renderer, particle system, etc) then these techniques usually produce simpler/cleaner code with massive performance benefits over regular approaches.

    • @JumpCatStudio102
      @JumpCatStudio102 Рік тому +2

      @@slipster216 thank you for your detailed answer. There is a lot for me to dig in now. I wish that there is a project template with advanced architecture like this to learn.

    • @slipster216
      @slipster216  Рік тому +3

      @@JumpCatStudio102 This is what DOTS is all about in Unity, though I've tried to keep this talk way higher level than that stuff is.

  • @thefogify
    @thefogify Рік тому

    great talk, thank you!

  • @thev01d12
    @thev01d12 Місяць тому

    How do we populate each monster data struct inside the array of 1000 elements ? Since the job can do operations on the data but the data needs to be present beforehand right ? What is the most efficient way of doing that and assigning the output values to respective Monobehaviors to update the UI and stuff.

  • @desenholdb
    @desenholdb Рік тому

    Amazing talk, thanks a lot!

  • @stefan429
    @stefan429 Рік тому

    wonderful and inspiring talk! one qualm i have with the step at 8:05 is the jump in complexity from changing to a struct from a MB. its not as simple as just changing the class to a struct, like how do you instantiate the monster associated with the data? if your config is a ScriptableObject, how do you reference the config to the mutable struct data? what if you want to destroy the monster game object on death, how is that accomplished?

    • @slipster216
      @slipster216  Рік тому +1

      If you want a dynamic list you can just use a List instead of an array, or keep an end value for the array and reorder the array when removing one. You can also allocate the max monsters you need for the game ever and give them a dead struct/flag/bit/whatever because iterating over all of them as is still 280 times faster than the original code. The point is this is a synthetic example to show the difference in speed, not to cover every data management case you might need in an actual game.
      For instance, in something like Unity's ECS you can do queries to grab data in this format, saying essentially "Give me all monsters with health and stamina but without a dead component", and it will return you a Native Array to iterate over with all of that data in linear memory.

  • @simonnordon8421
    @simonnordon8421 Рік тому

    great video

  • @Smileynator
    @Smileynator Рік тому

    Great talk, this sure vibes with me a lot more than the extreme data oriented approaches with most of the benefits.
    I have a follow up question i hope you could answer.
    I often do not get too much say in design decisions, besides guarding against the worst of the worst decisions from a code perspective. So if you take your monster example, our game would definitely then have like 10 types of monsters, each with different stats that are relevant and all sorts of inheritance going on. Making that whole example a lot more inefficient, or sometimes certain requirements make it downright impossible to have them all keep the same base class, and thus do a lot of the optimizations that you suggest.
    How would you approach that situation?
    Even more detailed, 9/10 times, my problems are not even code related, the entire game is neatly event driven and runs all it's code within 1ms of the total even on the worst of devices. But then some bright idea like "Let's add a post-process bloom, and 3 background layers causing severe overdraw" is what does the framerates in. I am not clever with shaders, and some of those problems i wouldn't even know how to adress properly even if i did know my shaders, because of the cheer incompatible effect types they are layering on the game. How do you deal with those situations? Pushing back harder, eat the consequences?

    • @slipster216
      @slipster216  Рік тому +1

      If your game code is not your bottleneck it might be better not to refactor that and focus on the other stuff. However, it's really a mindset of finding the commonalities and breaking the transforms you're making to data into passes, instead of having each thing operate itself. So instead of a monster doing "If I'm alive, based on my goal state, run forward", your doing "for all monsters" passes through the data - "Check alive, if not, add to dead list", "Remove all dead things from monster list", "compute all goal states", "Apply all movement states", etc. The differences between your creatures are likely a lot less than the commonalities.
      In most cases, shaders are no different than CPU code - it's all about how much memory your accessing. Luckily shaders operate in a DoD style already, processing clusters of pixels together in parallel instead of one at a time. For something like multiple post processing layers, you can often speed things up by performing all of the tasks in one shader instead of several, etc.

    • @Smileynator
      @Smileynator Рік тому

      That makes a lot of sense. I suppose i should focus on learning how to improve the visual effects then, as my game code really isn't the bottleneck. Your example does help for when i have more complex CPU processes to break down. Thanks for all the insights!

  • @damislav
    @damislav Рік тому

    Really cool thanks sir

  • @yeonghokim
    @yeonghokim Рік тому

    So, in the monster example, what we actually should do in a real game would be, when initializing the monster data, to instantiate the Game Object for the engine part(rendering, audio, etc) and keep the reference inside the monster data and in the every update in the monster manager, we should convey some of rendering information back to the game object. In this case, I suspect the performance cost of the engine part would be still high and may dominate the overall performance cost, and the performance gain from the logic part by DoD would be dwarfed by it. What do you think? Of course, you showed that we can directly rendering from data using APIs without depending on Unity game objects, but in most case we have to work with artists, and I guess completely not depending on game objects are not applicable in general when it come to using Unity.

    • @slipster216
      @slipster216  Рік тому +1

      You're thinking about it in a really traditional "Unity" way - heavily oriented around the concept of 'Objects' which are a human concept, not something a computer really knows or cares about. Many engines don't even have the concept of Game Object, and in Unity using ECS/DOTS you can work without that concept as well. You wouldn't want monster data, as an example, to have a pointer to a game object because then you're going to thrash the cache jumping around in memory (not to mention DOTS specifically wouldn't allow you to do this anyway).
      In an ECS system like DOTS, you can think of the entity system as a kind of DB to gather up data for processing- essentially you can say something like "Give me everything with an AIState and AnimationState structure" and it will return you arrays of that data for the entire game in nice, linear memory for processing. Then you can run a job which takes the AIState and applies it to the AnimationState - again, for everything in the game, processed in linear memory. Then, a separate request might gather everything with an AnimationState and advance the animation system for rendering, while another job comes along and renders every object. Rather than working one object at a time, with that object interacting with dozens of components all over memory, you work in sweeps across "All things with X, Y, Z" transforming the data all at once and efficiently.
      Artist tooling is completely tangental to this- Unity doesn't have good artist tooling for it's ECS workflows, but that has nothing to do with the coding model. The Turbine Engine, back when I was doing MMOs in the 90's, had state of the art tooling over a DoD style coding model. It's why we could handle thousands of players with full physics on the server with what would now be the processing power of a cell phone.

    • @yeonghokim
      @yeonghokim Рік тому

      ​@@slipster216 Makes sense. Thank you for the detailed, insightful answer.

  • @TopMeadowInc
    @TopMeadowInc Рік тому

    Good stuff here!

  • @stefan429
    @stefan429 Рік тому

    ive been testing some of these on my end and found that around 15:00 removing the config state and using just NativeArray is slower than using MonsterData (with 10m objects, monData is 2.8ms vs 4.4ms with the floats). this makes no sense to me, so perhaps the setup of the job is a bit different between us? mine basically looks like the monsterData job but hardcodes the config state.
    basically what im asking is for a more in depth video on this stuff! :D

    • @slipster216
      @slipster216  Рік тому +1

      You can download the source to my versions from my github (also posted on my blog). It's quite possible you're seeing a difference in array of struct vs struct of arrays. With separate arrays, you pass over each array once - which means more data can be prefetched by the cache. However, with an array of struct you can pass over the data once, with each element you're fetching being larger (so less prefetch). So depending on how much data you need, and how many things need access to it, you might want to structure your data differently for maximum speed. And sometimes it can be worth reorganizing your data between array of struct and struct of array for the particular task at hand. But my advice is to just get your memory into something more optimized than what an OO model encourages, because it's going to be many times faster - and then you can play with those layouts or do classic optimizations on calculations and they can actually matter again (because without fixing the memory layout, classic optimizations to save calculations rarely matter).
      Anyway, there's obviously a lot more that could be discussed here, but the point of this video was to get people to start thinking about memory access patterns and realizing what a huge deal they are.

  • @0x96
    @0x96 Рік тому

    thank you very much :)

  • @assemblyrtsdev
    @assemblyrtsdev Рік тому

    Great talk!
    15:24 so instead of iterating an array of structs, iterating multiple arrays of primitive types at the same time is actually faster. I didn't know that 👍
    Does Unity's ECS with ISystem and IJobEntity codegen magic utilize this optimization technique?
    I actually assumed that iterating over an array of structs would be faster because of it being contiguous, without the CPU having to jump between different arrays.
    I guess repeatedly jumping between a few different arrays isn't expensive because of CPU caching.

    • @slipster216
      @slipster216  Рік тому

      No, the optimization there is making the regen rate and max value a single value for everything in the array. This means instead of loading a struct with 3 values, we're only loading one value, so we get faster processing because we have reduced the total amount of data we're loading to 1/3rd.

    • @assemblyrtsdev
      @assemblyrtsdev Рік тому

      @@slipster216 I see, thanks for the clarification.
      Why did you split the array of structs into two float arrays instead of an array with smaller structs in your example?

    • @slipster216
      @slipster216  Рік тому +2

      @@assemblyrtsdev In theory other code may need health but not stamina, so having it separate means some other code won't have to load stamina as well as health.

  • @jeffomatic
    @jeffomatic Рік тому +1

    Thanks for the great talk! As a Unity dev, I'm curious about the "last mile" problem: how does an array-based representation of state connect (if at all) back to the rest of the engine, which is oriented around GameObjects? Off the top of my head, I'd guess that you either a) have a routine to copy the result of your array-based computation back to GameObjects, or b) if your use-case is truly isolated, skip GameObjects entirely and talk to the renderer directly. Do you have any pointers/examples on how to approach this?

    • @slipster216
      @slipster216  Рік тому

      Do you actually need the state on the game object? In most cases, you don't. There's no reason to have a rocket class at all, because the manager can just move the transforms of the rocket game objects around itself - they are just dumb graphics representations. For instance, in a monster example, what needs to be conveyed back to the game object is things like transform state, animation state, etc. In many cases you can directly render the result, as in the planet rendering case. And if you really want to be able to "have the state on the game object", you can always store an index into the array data instead of storing the state there (though you'll soon find that's just an unnecessary indirection). In ECS systems, for instance, the entity is just an id which allows you to lookup the data associated with it from various arrays of data. A Unity GameObject is just a very heavy weight version of an ECS entity in many ways - the monobehaviors on them are actually just stored in arrays of each component type under the hood, and the game object has a way to know which indexes in those arrays is there data. You can prove this because if you use FindAllOfType it returns that list of components in linear memory order. If you iterate over that list and manually call a function on them, it will run faster than if you shuffle that list and then run the same function. So internally we know Unity is allocating an array of each component type, and FindAllOfType just returns you that array.

    • @jeffomatic
      @jeffomatic Рік тому

      @@slipster216 Agreed! When I said "copy the result of your array-based computation", I was thinking of relatively primitive stuff, like positions and rotations.
      The note about components being stored in linear memory is an interesting one. It makes sense, given that the frame lifecycle is "striped" so that Update/FixedUpdate get grouped by component type. That makes me wonder how they deal with component lifetimes, e.g. a case where a component in the middle of the list gets logically destroyed. Not having seen the Unity source, I'd imagine they have per-component flag or free list of array indexes that aren't active anymore. Do you find yourself having to do analogous lifetime-wrangling for your manager systems?

  • @temper8281
    @temper8281 Рік тому

    Isn't slide at 4:44 actually worse? If the left OO slide, position and vel are together. On the right side, they are maxRockets apart which could exceed a cache line. As long as the Rocket (on the left) is in a contiguous array (and assuming Update gets inlined) isn't that actually more data oriented than the right slide?

    • @slipster216
      @slipster216  Рік тому +2

      No, because Rocket is a class allocated for each rocket, each one can be in a completely different areas of memory, causing a cache miss for every rocket. With the RocketMgr version, there are two arrays being read, but they are in continuous memory. In this case a slightly faster implementation might be to have an array of struct with position and velocity combined, but the assumption here is that there will be more parameters added and some won't be needed on every transform, so having them be separate is better. (IE: If we have 10 vectors of parameters, but the motion update only requires two, we don't want to load all 10 because they are in the same struct)

    • @slipster216
      @slipster216  Рік тому +1

      But you are right IF the classes could be guarantee'd to be in memory order, and we weren't going to add more parameters, and if the function overhead of the Update call was not incurred (none of which are true with Unity's framework, in this case).

    • @temper8281
      @temper8281 Рік тому +1

      @@slipster216 Thanks for the answer!

  • @awesomeniac
    @awesomeniac Рік тому

    @Jason Booth is the case about unity built in math library still happened on the latest unity version?

    • @slipster216
      @slipster216  Рік тому +1

      If you use Mathf, yeah, that hasn’t changed. But the new mathematics library is much better.

    • @awesomeniac
      @awesomeniac Рік тому

      @@slipster216 interesting, are they not planning to improve the built in math library? 🤔

    • @slipster216
      @slipster216  Рік тому

      @@awesomeniac very doubtful, it's been like that since the beginning and they have a new one now.

  • @PileOPoop1
    @PileOPoop1 Рік тому

    Twitter won't like this

  • @ZacharyHelm
    @ZacharyHelm 10 місяців тому

    Ahhhh, so the real ECS was the friends we made along the way/the concepts from this video.

  • @emagotis
    @emagotis Рік тому

    Hmm let's see what you have to show.

    • @theog5719
      @theog5719 Рік тому +14

      The heck does that even mean?

  • @子维-u1g
    @子维-u1g Рік тому

    The things you talked about are just simple things in the game industry.
    The first thing is just the ECS framework, which has nothing to do with "clean" code.
    Then you talked about job system, which even requires the code to ne clean since m-ulti threaded cpu code is hard to debug.
    The next thing is just AOS(array of structures) bs. SOA, again either has anything to do with code readability .

    • @slipster216
      @slipster216  Рік тому +17

      Who said this was about clean code? Also I don't talk about ECS at all.

    • @axeldaguerre8838
      @axeldaguerre8838 Рік тому +1

      @@slipster216 I had hard time to understand his point too

  • @ricanteja
    @ricanteja Рік тому

    You make it look easy! Thanks for this video, great info!

  • @Valentyn90A
    @Valentyn90A 16 днів тому

    Awesome channel