How the Unity C# Job System Works

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello everybody and welcome to today's video we're gonna be talking about the c-sharp job system in unity specifically I'm gonna be talking about how exactly the c-sharp job system works to give you a better understanding of what's going on behind the scenes no no there are plenty of videos out there showing you how to use the c-sharp job system and take advantage of all the massive performance benefits from it but today I want you to focus on how exactly it works so by the end of this video you'll have a better understanding of how the C sharp job system works which will allow you to make better decisions on when you should use the C sharp job system and it'll also help you down the line if you start to run into some issues with it and it's gonna make it much more easy for you to debug some of those issues and then in future videos I'm gonna be going in a little bit more in depth to some of the more advanced concepts so if there is anything specific that you want to learn related to the C sharp job system or how it even integrates into e CS definitely let me know down in the comment section below also you're more than welcome to join our discord community it's a great place for you to go and ask some questions and just share knowledge about game development that you may have and before I get into it I'd just like to say if you found this video helpful when you enjoyed it make sure you hit that like button also feel free to subscribe the channel for lots more videos on features related to the Unity game engine alright so let's get into the c-sharp job system now the c-sharp job system provides us a way to easily manage multi-threading within unity so before I go into kind of the specifics of the c-sharp job system I think it would be a good idea for me to just kind of briefly go over what is multi-threading so typically when you write a simple program basically you're writing out a list of instructions for your computer to you know calculate or do some certain operations on so it's a very simple example let's say the computer that you're running your program on just has a single core CPU so this means that the CPU not only has to iterate through all the instructions of your code line by line it also has to do all the background processes related to the operating system and everything like that so in order to properly do this the CPU needs to do something known as context switching so basically what happens during context switching is the state of the application is essentially saved and then the CPU can move on to something else process that for a little bit it'll save the stay of that that would go back to the other thing that it was working on and kind of continued and it kind of goes back and forth between all these different things now as you can imagine this is very you know processor intensive luckily modern computers ship with CPUs that have multiple cores so we can actually start cutting dividing up work between these multiple cores to avoid context switching so this allows our computer to run the operating system and background processes on a couple of the CPU cores and then we can run our application on a different CPU core and then it actually even goes one level deeper than that so we can start multi-threading within our single application so that we can kind of divide our work from our one application across multiple threads now when I talk about threads in general you're gonna have one thread per logical CPU core on your computer now I say logical CPU core because many computers take advantage of what is known as hyper threading nowadays we can actually have two logical CPU cores per physical core so for example my computer has a quad-core CPU which means I have four physical cores on my computer however because of hyper threading actually have eight logical cores so that means I can use up to eight individual threads on my single CPU so now a very high-level overview of multi-threading basically your applications gonna be running on the main thread and then from there it's going to schedule out work across worker threads now these worker threads are otherwise idle logical CPU cores which can take some of the load off of the main thread so then these worker threads will perform their work and then they'll sink their results back with the main thread now directly managing multi-threaded code can be quite challenging for a number of reasons one easy to describe reason is because you don't always know exactly how many logical CPU cores the endpoint device that you're gonna be running your game on is going to have so you can't just say hey I want to perform this work on CPU core number eight because you don't know that that device is actually going to have eight CPU cores for you to run on and because of this unity created something known as the c-sharp job system and the c-sharp job system is a really elegant solution to this problem because basically you as the programmer you don't need to worry about how many as the end device has or how to exactly schedule them I'll use the programmer do is define the work that needs to be scheduled out on one of these worker threads in the c-sharp job system take care of the rest and the way you actually do this is by creating what is known as a job and a job is basically just a small unit of work that does a specific task on some certain data that you pass into it so basically in your main thread you're going to define the job and the data it has access to and then the job is actually going to operate on that data and then it will return its results to the main thread so a lot of times these jobs are self-contained and basically just kind of run independently but sometimes these jobs actually are dependent on the results of other jobs and so we'll be getting into more of the specifics on how dependencies work in another video but basically we can make the program so that if we have one job that depends on another job we can ensure that this job runs after the other job all right so once we've created our job the next step we need to do is to schedule it and so scheduling it basically queues it up within the job system and then the job system will assign it to different worker threads so essentially these worker threads are otherwise idle CPU cores that can kind of pull from the queue and run these jobs and then it can return the results back to the main thread all right so everything sounded good so far well we're gonna be talking about some of the issues with multi-threaded code and one of the main issues that we can run into is something known as a race condition now a race condition is something that happens when we try to basically access the same bit of data from two different threads of course because these two different threads can't talk to each other and neither of them know what each other is working on we can run into some weird issues alright so here's a simple example of a race condition so let's say we have a variable X and we'll set X equal to one so off the main thread we can schedule a job that says let's take the value of x we'll multiply it by two and return that to the value of x and then we'll so say on the main thread after that we'll take the value of X and we'll add one to it and then return that value to X so now what we have here is what's known as a race condition and so it's a race condition because the result depends on timing of how these things are actually executed so for example again if we're starting with the value of X is equal to 1 and then we run the job on the worker thread first then this is going to multiply that value by 2 so we'll have the value of 2 and then after that the main thread does its operation so it adds 1 to that value so then we'll end up with a value of 3 however we could run into a condition where the main thread operates first and we'll add 1 to the value of 1/2 that's a value of 2 and then our worker thread runs after that so now we'll multiply it by 2 and we'll end up with a value of 4 for X so then you can see how this can start causing problems because we can't guarantee the order of execution of things on different worker threads and the main thread however the engineers over at Unity already thought of this and they put in some built-in safety measures to avoid these certain race conditions so instead of the job system simply passing references to data into these different jobs it actually passes a copy of the data into the jobs now this is very important because this means that the data types that we use must be little data types now AB little data type is essentially a variable type that can be transferred between managed and unmanaged code so typically in c-sharp and unity we're gonna be writing managed code where unity' takes care of all the memory allocation and garbage collection and things like that and then the unmanaged or native code that's going to be much more low-level or actually working with direct memory access so basically we make copies of this data so different worker threads can look at that data and do different operations on it and avoid race conditions however because we have that data isolated to a worker thread it doesn't allow us to easily sync that data back with the main thread and that's ultimately what we want because that's where the bulk of our game is going to be running is on the main thread so in order to overcome that unity created something known as a native container now the most common type of native container is a native array and it's basically a wrapper for this you know unmanaged native data that we can access from managed code and so when we get into ECS programmer and we're going to have more types of native containers at our disposal such as native lists native hashmaps native multi hashmaps and native cues and these native containers have built-in safety functions so for example there's the disposed Sentinel function which detects different memory leaks and then there's also the atomic safety handle and that basically tracks what thread has access to that data and so it's going to make sure that you're not writing to some data that some other thread has read and write access to so by default these native containers have read and write access to the data that you specify however that can cause kind of slow performance so if possible you want to have read only access set on these native containers but of course there are going to be some times that you need to write to the data so just be sure to use that only when you actually need it and there is one thing to note that's kind of related to this is unity actually does not provide any protection for reading from and writing to any static data and they warned you that this can kind of cause some issues and it may even crash unity so definitely be careful with that if that is something that you ever end up doing so don't miss I'm gonna wrap up this video right here I think in a future video I'm going to be going a little bit more in depth on some dependencies and some more topics related to the c-sharp job system and unity and then especially talking about how it integrates with ECS again if you do have any questions or suggestions for future videos especially related to the c-sharp job system definitely let me know down in the comments section below once again and I highly encourage you to join our discord community you can go there and ask any questions and share any related knowledge that you may have once again if you did enjoy this video and you found it helpful I'd really appreciate it if you hit that like button also feel free to subscribe the channel for lots more videos on features come into the Unity game engine and if that's ok all fantastic rest of your day I'll see you the next one [Music]
Info
Channel: Turbo Makes Games
Views: 1,683
Rating: undefined out of 5
Keywords: game development, how to make video games, making games quickly and effectively, turbo makes games, johnny turbo game development, home cooked games, unity3d, game design, video game programming, game development for beginners asdf, game development for beginners, how to use unity, c# job, c# jobs, c# job system, c# job system unity, c# jobs unity, c# job system ecs, c# programming jobs, unity multithreading, unity multithreading tutorial, unity multithreaded job system
Id: Iwj0_p0bLpc
Channel Id: undefined
Length: 10min 49sec (649 seconds)
Published: Tue Jun 02 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.