#20 - Dart Isolates, Threads, The Event Loop, Microtasks, Synchronous & Asynchronous workflows

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what is going on everyone i'm wicked welcome back to my channel today for the first time we'll dive into what's probably the most important and advanced chapter of this start from novice to expert tutorial series synchronous and asynchronous dart workflows this chapter has a really high difficulty level as a result in order to make the learning curve easier i have split this chapter into three major parts today we'll tackle the first part in which i'll talk extensively about the difference between synchronous and asynchronous workflows what are the particularities of a dart isolate in which we can find these workflows and a bunch of really interesting examples that will challenge you while also making you understand all unique aspects of how each and every sequence of dart code runs behind the scenes so without further introduction let's get right into this tutorial ok first and foremost in order to grasp all concepts in the most straightforward manner let's move the tutorial inside a simple factory i want you to pay attention to every detail i'll be mentioning about this factory and the people working inside of it on the left side of the factory there is this motorized royal platform delivering boxes on the opposite side there is a shelf and on top of it there is also a screen showing which boxes are going to come soon down the line today at the end of the roller there is a guy called john john is the factory's math guru he's able to calculate every possible expression as fast as a computer he's a genius and god knows only how it ended up working in this factory the salary might have been really attractive i guess john started his shift a couple of minutes ago and is still waiting for the first couple of boxes to show up he has the ability to stop the roller whenever a box comes by using the buttons next to his post inside each of these boxes there is an expression that needs to be calculated john's job is to take each box out of the roller one at a time open it retrieve the expression calculate it write the result on the box with a marker then place it on the shelves next to him at the end the paper having the expression will be tossed away into a trash container which is also conveniently located next to john sometimes nobody knows exactly when another guy called michael comes and empties the trash or any other residues left around after john's intense brain process okay now that we got this in mind let's simulate a couple of minutes of john's job out of nowhere 5 boxes come down the roller john stops the roller retrieves the first one opens it calculates the expression writes down the answer on the box places it on the shelves next to him and throws the paper with the expression in the trash can he turns the roller back on the second box comes in line takes it turns the machine back off again calculates the expression places the box on the shelves and throws the residue in the trashcan right after it then again the platform moves delivering the next box the same thing happens with the third box too it gets calculated placed on the shelves up following the same order of events i want you to notice one really important aspect right now all of these boxes are processed synchronously meaning that in order for john to move to the next box in line the expression for the current box needs to be calculated this is a synchronous workflow in which you can't move to the next step without solving out the current one for the fourth box however john witnesses something he never experienced before he stops the roller opens the box and inside of it there was nothing but a message from his boss the message was saying that one of the guys in charge of creating the expression went to the nearest coffee shop for 5 minutes therefore this box ended up empty he promises though that after 5 minutes in the future the guy will deliver the expression directly since he will have it written on the road back to the factory john already has an empty box so it makes sense to receive just the content for the box in the future now if jon would be a robot being able to only process things synchronously then the entire queue of incoming boxes would have remained blocked and unprocessed until that game came out with the expression so that john could calculate it and move on to the next box however john is smart and he decides to handle this event asynchronously john will take his boss's words for granted more like as a promise that sometime after 5 minutes we don't know exactly when the expression will come down the line so he could calculate it and assign it to the box he believed that there's no need to hold the entire production line just to wait for an answer that may come after 5 minutes or more than that since this operation allows processing of other boxes while waiting for the expression of the another one we call this an asynchronous operation as a result john takes the box as it is and puts it unmarked on the shelf next to the other ones know that if somebody comes to the shelf and asks what's the answer of this box john will tell him that it's just a box with no number yet but it will have a result coming out soon having this said john moves on to the next box waiting in the queue and processes it calculates the expression then marks it with the proper answer after this is done john gets in an idling position since there are no new boxes coming out on the screen while he's waiting michael may come and clean the trash can filled with calculated expressions as they're not needed anymore one thing to be noted is that michael can happen to come at any time even when jon is working in order to clean up things he isn't always waiting for john to finish all the boxes what if jon had 1000 boxes to process then the trashcan would have been filled to the top in a matter of seconds that's why michael will come by regularly to check the situation finally after he's been waiting for more than 5 minutes the envelope containing the expression for the unmarked box arrives down the roller john takes it calculates the answer and goes right ahead and assigns it to the unmarked box now all boxes are marked and there are no other boxes coming down the line so he feels free to shut down the factory and call it a day john wants to highlight after this hard day of work that if you find this tutorial really useful and you appreciate the way i teach these concepts please make sure to share the video hit that like and subscribe button and consider hitting the notification bell so that you'll know when i post a new video also make sure to follow me on twitter at let's get wicked this is where i'm at most of the time having this said let's get back to our tutorial now you might be wondering well okay so what's the point of this wicked you will be absolutely surprised but what i'm going to tell you now but the reality is that this factory is the exact representation of an isolate in dart an isolate is the place where all of the code you write inside a dart program runs you don't believe me say we have this exact dart program now i want you to carefully look at it line by line and tell me if you observe a pattern of course this code is the exact representation of all boxes john processed that day you can see that the first three lines of code correspond to the first three boxes he was able to calculate and write the result of their expression right on them then as a surprise the fourth line of code got processed represented by the fourth box with a feature that's delayed in which his boss promised that the expression would eventually come after 5 minutes john moves asynchronously to the 5th box solves it as before then gets it into an idle state waiting for the previous promised expression to arrive finally after 5 minutes well in our case for demonstration purposes 5 seconds the expression arrives john calculates and assigns it to the unmarked box then calls it a day therefore killing the running cycle of our program now if we run this exact same problem you'll observe from the terminal that exactly the same things happen just as we described them so having this in mind let's compare a real isolate with this factory example and associate each of these components to their technical definitions when we run a dart or a flutter program the execution starts exactly from the file containing the main function from there dart spawns an isolate an isolate having the same name as the main function made an isolate is a component specialized in running the code this isolate is basically the factory we've been talking about now one really important particularity of dart language is that it is a single thread programming language this means that all operations you will code inside any of your programs will be executed on a single thread of execution one at a time one after another one this is exactly why we have only one ruler in the factory the roller represents the single threading characteristic multiple threads would have meant multiple rollers but for dart it is not the case as everything works single threaded this single thread of execution is technically called the mutator thread pay attention i'm talking about the motorized roller and not the boxes that come down the line on it the only one motorized roller represents a single thread now you might be wondering what those boxes coming down the line represent well in our case in the simple dart app we run they represent lines of code that will get processed one by one but in a flutter app for example they might also represent other commands like rendering some components of the user interface or retrieving screen tabs generally speaking these boxes represent events issued by the app running in the isolate the entire line of boxes building up on the roller represent the event queue note one really interesting fact though when scanning for events dart always does it synchronously for example you don't see dart going from line 1 to line 3 to line 4 then coming back to line 2 when executing the code thus issuing the boxes now instead it will go line by line from line 1 to line 100 consecutively one at a time the key difference here is that the events will always be issued synchronously but they can be processed both synchronously and asynchronously and the guy in charge of processing the events is john john is the event loop and he represents the brains of the operation his brain is the event handler deciding what to do with the box that just arrived when he sees that a couple of events will arrive he'll process them one at a time in the order in which they arrive if one of the events specifies that it will deliver its content in the future then jon will still process the box place it on the shelf then move on to the next box event this results in dart's asynchrony support so as you can see asynchronous operations in dart aren't done on a separate thread as you might think but rather on the same thread the only difference asynchronous operations make compared to the synchronous operations is that even though you don't have a response for an event yet you can get to process other events until that response finally comes in a synchronous workflow that wouldn't be possible i hope you get the idea we use asynchronous workflows if we know for example that a task may take an undetermined amount of time to complete and we won't want to freeze the entire app until we get an answer from it for example a network request from an api may take an undetermined amount of time storing a file on the internal storage on a device may take also an undetermined amount of time maybe one phone has faster ufs storage than other essentially everything that may take an undetermined amount of time to be calculated should be tackled in an asynchronous manner so okay john processes the incoming events but what does this shelf represent where he seems to place all results well this shelf represents the isolates internal memory so whenever you write something like var a equals add of 3 and 5 john will create a new integer object with a value of 8 on this memory shelf and then he will assign the a variable to it through a pointer the variable just points and accesses that value in the memory it is not included in the object by itself you might imagine that not all processed events may end up in storing stuff on the memory take a tap of a screen for example if a user taps on an area with no functionality then john will handle the tab but do nothing in exchange the screen above the shelf represents the dart code the isolate runs because at the end of the day this is where it's stored and this is where the events come from now there is only one character left that it's worth disgusting we've encountered him occasionally in the factory michael used to come from time to time to empty the box of residues left after the intense calculations john was doing for every box michael is called a helper thread a thread which is specialized in his case in garbage collection but wait wicked you said that dart is a single threaded well dart is single threaded when it comes to event processing all instructions and events come and are processed on a single thread but operations related to the isolates well-being are handled by other internal threads found inside an isolate now i hope you finally understood how an isolate works especially after assimilating it to a normal factory you might have a couple of questions right now at least i would have some when we run an application is it really just a single isolate spawned to manage all code and the answer to this question is yes when running dart code only one isolate is spawned to take care of it one isolate with a single thread of execution okay then but isn't that limiting what is going to happen if john the event loop has to calculate a really huge amount of information perhaps a sum from one to this number i cannot even read we know how much is it going to take and it is going to take a lot of time but the event loop has to process it there is no way to bypass it since it's synchronous then all of the events waiting in the queue will have to wait a lot of time for the event loop to handle the calculation of course this is a limitation of dart for being a single threaded programming language but is there a solution on how we can improve this yes it is it's called parallelism running the code in parallel even though dart starts running the code in one single isolate called main we as developers can write code to spawn another isolate in which we can send this huge calculation event to be processed in this way while isolate number 2 will be busy calculating that huge sum isolate number 1 will still be able to process the rest of the events coming down the line so yeah dart can run code in parallel by creating multiple isolates but unfortunately at this time creating multiple isolates comes at a cost as they are really expensive resource it's also pretty hard to communicate with each other each isolate comes with its own memory and sending messages between one another can be done only via control and send ports so it's not really ideal however for now it's the only solution for our problem imagine that currently spawning around 150 isolates takes around 850 megabytes of ram and that's because each one of them has its own dedicated memory inside 1000 isolates can take up to 4.5 gigabytes of ram which is a lot especially for a mobile device however thanks to the amazing dart team they announced that soon perhaps in dart version 2.15 a new version of isolates will be released they will be called isolate groups an isolate group can contain multiple isolates but this time those isolates won't have their own dedicated memory but will rather share the same global amount of memory inside the group between each other i can't tell you how excited i am and you should be too for this change imagine that not only the amount of consumed ram will be exponentially lower but the communication between isolates will be more facile since they now will access the same memory developers will be able to spawn multiple isolates for parallel intensive work to ease the usage on the main isolate many many advantages are going to come with this new change believe me dark developers benchmark this new change and if previous standalone isolates took approximately 4.5 gigabytes of ram for 1 000 pound isolates well these isolate groups are able to spawn 10 000 isolates for just under 350 megabytes of ram now if this doesn't seem efficient to you i don't know what else is now before i end this long tutorial first and foremost i want you to take a closer look at what i told you about the event queue and the event loop from inside an isolate you need to know that besides this event queue that may form out here there's also another cue called the microtask queue it's not another roller it's just a way of saying that some elements have higher priority of being processed than others don't worry it's really nothing all that different or special micro task queues are designed so that if you have for example three features and you want some of them to be calculated earlier you need to declare them as micro tasks and they'll be calculated before the other features i know it may sound a little bit strange at first and that's why i want you to try and guess the output of the separate programs i'm showing on the screen right now after you've done reasoning we'll simulate them together it will make the most sense this way believe me go ahead and pause the video and give it a try on how all these events are accounted for and processed by our friend john so if you're done let's simulate them together one at a time we'll start with the first one here's a minimalist representation of the main isolate that will run this program we have the micro task queue the event queue and the event loop that will handle both of these queues i'll name each event after the letter that's going to be printed so that we can track them more easily first event coming is event a which is being taken care of synchronously by the event loop so it prints out a and gets rid of it from the queue the next event coming is this big future it is a future so it's being taken care of asynchronously as its content is going to be processed later on so we'll put it somewhere later in the queue then event g will arrive that will be processed synchronously by the event loop and printed out so until now we have a and g printed on the screen sometimes in the future the content of this previous feature will arrive in the event queue one by one the first event is event b which is processed synchronously then printed out then we have another feature coming down the event queue so because it's a future we'll process it asynchronously because we are sure that the print c callback will arrive later on again in the event queue therefore we'll place it again somewhere at the back of the event queue now here's something interesting the next event is a future.microtask this means that it's a microtask event that will come in the future with a callback that's going to print the letter d so we will assign it to the microtask queue next up another feature that will come in the future as an event with a callback printing e so we'll place it into the event queue but a little bit later on than the other one printing c finally we have another remaining event called f that we need to process and the event loop will print it on the screen as it's ready immediately in a synchronous manner now if there wasn't a microtask here the order in which each feature would have arrived to the event loop right now would have been c d and e right indeed but d is a microtask and whenever we have a bunch of futures coming down the event pipe the ones that are on the microtask queue have higher priority so they're going to be processed first having this said the event loop takes the d event processes it and prints it then it processes the last two events in order event c which prints c and event a which prints a again for the second case if there was no microtask the entire microtest queue would have remained empty along the run of the program either way microtasks are not something that you'll use very often the majority of time events will come down the event queue just as i showed you today oh and also don't worry if you don't really understand what a future is and how to work with them we'll learn every aspect of them in depth in the next two parts of this mini-series having this said i think it is finally time to end the part 2 of this huge dart sync and async workflows chapter i hope you finally understand what an isolate is how dart handles a synchrony on a single thread and what's the difference between synchronous and asynchronous operations in the next part i'm going to dive into every characteristic of synchronous workflows discussing and displaying everything you need to know about synchronously playing with one or more values as always if you like this tutorial don't forget to smash that like button subscribe to my channel and share the video with all of your friends and colleagues in pursuit of top tier development until next time as always take care wicked is out bye bye
Info
Channel: Flutterly
Views: 2,011
Rating: undefined out of 5
Keywords: dart, darttutorial, dart course, dart isolate, dart isolates, dart parallelism, dart multiple isolates, dart isolate group, dart events, dart event loop, dart event queue, dart microtask, dart microtasks, dart microtask queue, dart single thread, dart single isolate, dart spawn isolate, dart async, dart sync, dart synchronous events, dart synchronous, dart asynchronous, dart asynchronous events
Id: ArbJhSsEwTk
Channel Id: undefined
Length: 24min 39sec (1479 seconds)
Published: Wed Sep 08 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.