Roman Elizarov — Structured concurrency

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so I've been working on verse you know big scale enterprise systems in a while and this ended me in the position of teaching concurrent distributed program here in Cynthia's work at ITT more University and now I'm working in JetBrains and we work on various libraries in language design for Kotlin and for me that's going to be a walk down the memory lane I will retell the design process that we went through the experiments we did when designing concurrency for Kotlin what we were sparing to is what changes in choices we met down the path and so this is going to be like I've never told this the whole story before in this how it unfolded so Alan share many lessons we learned and I hope they will be useful as were the concurrency design in Catlin originally was inspired by a sinker weight and what's the sink avoid I think it is a language feature that was first introduced to mates to him in c-sharp programming language who here program since you're sharp can you raise your hands oh good that's very number here we're good and who knows a sinker weight like anywhere c-sharp other languages who used a cinco it knows what a cinco it does including c-sharp assuming better that's great so that will something like this will look familiar to you that's how to sharpen usually introduced a sinker weight programming in mainstream so in c-sharp a synchronous programming as they did it starts with marking a function with I think modifier telling this is a special a synchronous function this function must return a future that in c-sharp called a task but it's it's still a future concept other others calls it differently promise you know deferred sounds like that but that's the same concept and you know they later extended it to more away table times but anyway and inside of a sync function you can call other functions that return a future and you can await for them the sequential fashion so your weight you can await the first operation and when it completes you know next one execute you can wait for it and when your weight nothing is blocked you know you know thread is free to do it's anything else oh it's really lightweight mechanism to do lots of lots of a synchronous or concurrent things with each other at the same time without blocking threads because a waiting does not block the underlying hub heavy weight operating systems thread and this model was really inspirational after she Harper to use it many other languages had taken it without my changes like it was really like it's one of the greatest ideas of the last ten years if you look at the number of you know followers and what it inspired so dart program language incorporated it JavaScript incorporated a sink await in into a standard typescript deed even before Java Script you know Python edit at some point a sink await and you know modified it through several iterations but again the inspiration was the same brass programming language is adding as enjoyed as we speak now it's like the difference at acting form but still conceptually the same thing and psychosis is also adding it in the upcoming standard so I mean this was with a radical idea it was really great and it also inspired cotton though because we wanted to be able to write this as internal software marker services to get into the modern world of lightweight concurrency so we looked at it and so how we can incorporate it and in c-sharp what await is awaited this a special keyword the basic remarks a suspension point that's a special place where compiler knows that you know you can suspend execution of this code you know spirit state somewhere so because when the operation complete has to be resumed again schedule turn to the heavyweight thread and continuous execution so this is points where you can suspend the execution but interestingly even before sync await c-sharp has another very similar feature and some other language is also headed like like Python that's yield return feature and who knows what is that what's your return than this usual place yeah it's it's used for waiting a synchronous sequences or unum or Abel's is they called in the net world an interesting inside c-sharp compiler in run time it has to do very similar thing than the synchronous syntactically to difference differently but internally it's very similar feature from compilers who support requires approximately same kind of afford for the compiler or language maintain yours but takes different sets of keywords so we in Kotlin you know cotton is this language that tries to be generic we are cuttings of idea cells you know minimizing number of hard-coded features and moving stuff into libraries so that people can create them in specific things with pure library so we wanted to generalize this we didn't want to have a bunch of different keywords in the language to support different very similar features we wanted a more general feature and our very first prototype that was done more than two years ago so almost three years ago we would like the more right now was envisioning support of a sink and waiting cutting like this so that in this prototype that how it would have looked in our original prototype and who assemble with Scotland here okay that's I mean cousin is like the same family of comes from a family of languages so it's not hard to understand what's going on so there's regular function Catalan and instead of adding a sync modifier to it and our regional prototype we said okay let's instead do this kind of builder and and you see it looks like built-in construct into the language but in fact they're just a function called syntax cotton you can when you have a trailing lambda then you can just and meet the score the wrong brackets and just put curly braces and put at the end and that's kind of common feature meaning some other languages say that we in here we kind of were aspiring to groovy with this feature but like swift also has it so it's appropriate featuring modern languages and it lets us you know instead of adding like keywords and constructs into the language we can just define them in a library and then for users that look like built and things so that just it would be just a library function that calls some lambda and this lambda would use a magical cartoon scope that's scope where you can suspend things and a weight instead of being keyword like in c-sharp so original design original prototype went like this let's make it a function but this function has to be special compiler has to know that you know execution can be suspended here and resume later when the operation completes so it was we named it as a spending function in marked with a special modifier for compiler and that was our first prototype and then you know we have this await suspending function which let us do the whole a sink await DSL so instead of keywords it's just library basically they're now implements the whole I think away things and you know this unless you worked with futures or you can create another DSL or with generating yield and you make sequences whatever you want that's what's the aleutian part I'd everything he goes but then you know we looked at it and you see if a weight is not it keyword anymore it's just a function marked with suspend menu fire and why do we need it you know why not make those requests talking a create past the actual business function why not make them suspending functions why do we need this and way things interesting then we look further you know this thing now returns the future why do we need it we can mark functions as suspending ones let's just mark the whole operation suspending and now you know you look at this code and it's like looks like a regular code like like you did with blocking programming with threats it just you have this suspend modifier and the only telltale sign that you have some suspension is the IDE mark so ID would did the gutter the left would add this small science indicating where suspension happens and when we showed this proposal you know some people were scared like you can do this they said how would I review my PRS in a github you know I see the clock I don't see where did you wait here it's not visible in the source code name and there was a bit of discussion should we maybe add still has some syntactic mark at the call site you know to indicate in the source where suspension happens and we weren't really sure long we was just a prototype I mean we didn't really even release it yet we were just playing and we were kind of scary listening because everybody else doesn't do it like this like look everybody language that was in every other language that was inspired by soosh are passing kuwait and they always have this awake keyword each one of them and we didn't was a scary innovation you know we really were scared to put it forward but one guy say dust you know and you might have seen this guys this and you know who it is this is gopher ghost gopher and you know the same code in go program language looks like this you know awaiting the source code and people perfectly coded you know nobody war is that when you're doing PR they don't see where it might suspend if not even ID can show you because in in go program allege there's no different between function that will go over network and may suspend you for and minute or so and a function that does quick local computation there's nothing in the source nor in the IG to show you this difference and by the time we were prototyping this gopro knowledge was already gaining a lot of traction and we saw lots of confirmation that people are happy with with this programming model they don't get worried by the fact that they don't have to write a weight every time they do this lightweight you know suspension because in GoPro who manage everything is lightweight every there's you don't have direct access to this heavy weight threats you know all the goroutines are lightweight in your programming language so that finally convinced that that were key to go with the prototype we had and once now having a prototype of the language feature we started prototyping libraries it basically we started creating this domain specific language for concurrency seeing what we can do neither cotton anyway so in hard coding to the language let's see now giving this one language mechanism for suspending function what we can do a syllable and we're told transpiration because go program which was this last convincing straw that we are on the right path are we looked at your programming language and there's this nice site with a tour of lore that introduces all the gore concurrency features and was a nice really fun exercise just to try implement whatever God does in its language as a librarian cotton so the first exercise in the tour of go concurrency there is a little simple it shows you two key features of a go support for concurrency one key feature is this go keyword and then go is just a keyword you know starting new concurrent process you should go and some function a call and it starts and starts at you were written for you that works concurrently with the rest of your code and then inside this wording in these safe functions that you can use things like sleep so you can say oh I'll wait here and this sleep nothing it doesn't actually block a thread you know god scheduler would suspend this goo routine you know schedule the other one too and so it's really lightweight you know it's not like thread sleep in Java it does not block a heavyweight thread now aimed with this cotton support we prototype a very small trivial library's was really fun to look at this product of two years of the progress that does the same but as the library in Catalan and look like this so what we had to do we had and it didn't have to change a lot of go code if you bury difference between syntax we had to mark functions with suspend modifier that it's like you know this function that can suspend execution we had to rename this sleep because in GBM there is thread that sleep that extra block a thread we did not want confusion so we named it delay this has been a function that does not block in weight it does not block the thread it it you know we so because we have both threads and you know we have to distinguish we say it suspends the curtain in go world they don't expose thread so they they just use the word blocking we try to avoid it and instead of this go keyword in this prototype we had go curtain builder so just a function that takes a lambda and starts this concurrently so in it was really fun you can take then any example in go tour you to write the light by line into cotton it works just like or produce the same results it was so much fun so if you go further over this tutorial you know and the but the other thing you know that's we had to integrate it with your main function so we have this great this main blogging things so actually nowadays the same code did not much change we over time from prototype to the finalists we just renamed a few things you know main function up here became run blocking and instead of go we now say launch that's the finally we ended up choosing but it's still this the code you can run now and it just just works but then back then in a prototype we looked at we basically the worker who writing all this go concurrency examples into cotton just to see we can do it you know for example this example number five in go-to or foreign currency shows a use of channels so it defines function if you manage a function that takes two channels as parameters and what it does it actually sends Fibonacci numbers into first channel and receives a stop signal on the other channel so what it uses this select statement in go program which again in go is just hard coded think it's not the library feature it's hard-coded into the language in language runtime and inside you have this cases you can save us please sent to this channel if you can send and compute next to manager number and if you receive a quit signal then you know print quit in return and again it's a part of prototype we just rewrote it into Kotlin but it's a library so we defined channels as library types we define this select as calling DSL and again it's just using cotton DSL definition features which I'm not going in here it just you know what some nice experiment whether cotton can do it and it could so one more to which you know we implement a really small language feature just one simple support for suspending functions and we can do everything SSO library we can mimic go we can make any other concurrent language out there just as a library no need to new keywords hurt hard-coded support you won't have nothing done deal but not that fast because in original goals that were set up when this project was started we had one interesting thing that we wanted to support we wanted to support thread bound joy programming is something the government doesn't have to worry about it was designed to do back in programming with you know servers you know all many threads all concurrent but in Catalan is a general-purpose language its design was front-end back-end mobile web design - so there you can do anything in it and one of the use cases for Catalan was writing UI code and UI is this beast where you have this huge data structure called your UI state and it's thread bound you can only manipulate this data structure from us no threat you I said and in every UI framework that spoken nowadays has this thread bound restriction you can make many political structures only from the single thread whether it's mobile or desktop framework they're all in this respect the same so we had to support it somehow and the original vision was something like this we want it to be able to support a kind of a special construct launch UI so instead of just launching your curtain somewhere like an NGO that works in some backgrounds fateful that scheduler maintains for you we want you to say I want to launch a curtain that runs in UI thread because in your application you have lots of concurrent processes you know running animations respond to user events but they all because they manipulate your structures they have to be thread bound so that from this court in you can make requests for example to network but the end display result in UI may being completely shorted here still running in the same thread and we did it by add any concept of curtain context so instead of creating a separate launch function which is added an optional parameter to it that configures the execution context there is a default execution context that uses a thread pool and you can say I want it to be a UI execution context and by but here is the trick it's not enough in Kotlin to confine this illusion of this code in this curly braces to this thread it also has to work with higher-order functions using Kotlin lots of things that are key words in other languages like synchronizing Java is just a function in Kotlin so my programmer does not even realize when they write some like things like repeating code and a letter with iran they don't realize it just a standard library because it looks like a keyword in other languages but in fact what it does it calls a function passes it lambda and this function is some later time execute this lambda and during a synchronous programming higher-order function is not that straightforward let's take a look to understand why elastic to look at C sharp back in the doing which that inspired a sinc await in c-sharp if you write the same higher-order function it will look like this you'd say a waitron and pass at the lambda and its usual you have to be explicit there's no trailing on there you have to put it in you know and braces etc but that's that's basically jewelry right of this code in c-sharp 2010 was going on here we have to split it because in fact what happens there's actually two things here first you call this function run as a tell'em des and it returns to a task and then you await only a task so from standpoint of c-sharp this run function is just a regular function call it's not special it's a sync modifier is something that affects this implementation but on a call site is just a function returning a task so it's it just calls it and this function then somehow has to arrange the call of this lambda but what execution context for this num that it will use how do you propagate it you have two choices really explicitly pass this execution context a parameter or use some kind of thread locals and c-sharp you know some places does these so that and the results are not I know and we had a design inside let me tell so we've saw that you know people in c-sharp not happy with how it works with how this thread local based propagation works but in cotton solution came naturally because in Kotlin this high order function call is actually call to suspending function it's there's no separate called regular function in the weight it's one operation call suspending function and because we had to arrange for a special calling convention of this suspension function anyway we also edit ability to propagate execution context with this call so whenever you call suspending function inclusion contest is propagated so now whenever this function calls something else it can propagate its usual countries down the stream so contents get passed along the suspend call stack implicitly without us having to do it explicit and and this this is important for cotton because you know otherwise it's just a boilerplate and cotton is all about removing boilerplate from the user code code mean is all about making sure that your code has less more substance in it and less ceremony around different things not related to law the logic so that one works well but then we faced another challenge and this is the constellation and the constellation seems this doubling block of concurrency design many pointers tried it with not really satisfactory result Java is not really successful there with its thread interrupt and stuff JavaScript did not even include cancellation into its promised support after lots of discussions is huge discussion thread there's not fortune gradually through c-sharp you know has this concept consolation talking but you have to explicitly pass it into it's just boilerplate this passing down consolation talking's down the stream actually ever improves on that it uses c-sharp underlying libraries but it actually makes passing constellation implicit so actually work knee was Kinsella ball a synchronous function is essential Pleasant in f-sharp that was kind of one of the inspirations there but then you know if you look at copper image with was again well I could pinnacle of concurrency at the time we were designing this it was language too explicit design for parts a you thought it should support cancellation in a sense it does because this very example I shown you actually shows the state of the art of the consolation supporting your programming language so this quit channel yes a constellation talking that's what's called in in.net were the consolation talking is the so can you explicitly pass to make sure you can cancel this computation but the problem is then you have to explicitly remember about it read from it and process it so this was just a boilerplate every time you want to do something in cancelable way so we would ask is this really consolation support that's state resulting can we do something better and hot and the actually gets better every time you know if you look at more Morden go you know they have this thing called context and context actually it's much more rigid approach much more standardized in go program language to pass on consolation information it has this still has this channel called tonk but it comes with recommendation practices it's kind of interoperable between different libraries but still you know what you read in the documentation of this is that you know it requires got programmers to explicitly pass this context into every function which is on a pipeline between incoming requests and outgoing requests and when you're writing networking application that's where all your business logic is is between incoming and outgoing requests means everywhere you have to explicitly pass requests but in our world these functions that live on your purchasing people are suspending functions because they work with network and it's can you know suspend the execution until you know network is ready so we'll do mark these functions we don't want yet another parameter to pass so we wanted better and we went to prototyping board in our first prototype was called lifetime it was an interface that we can pass as the current in context because that one get explicitly propagated into all suspending functions it was really simple it has just two functions you can cancel it and you can install a completion listener get notified when it completes really simple thing it basically models I think with two states active and completed which explicit transition between them in this product ibuenas want long way through actually ended up renaming it to job so that's even an early birthday but it was already called a job for a while this very simple thing what what you can do with it now with this simple job object you can return it from things that launches recursion you can say when I launched something return me a job and remember you can cancel it so you can come cancel and when you can cancel because this job is in integrated into the context of this code it gets propagated to this safe function and it gets propagated to delay function that it uses there and delay function knows that it's cancelable so whenever cancels called its own completion handle it would sell cancellation exception and wind all the execution stack and terminate the job done deal we can now do explicitly cancel the job we launched what's even better we can easily create higher-order operators so we can say for example created with timeout the higher-order function that captures a job from the context it is called in creates another job and propagates it into the inner block so this other job gets cancelled when tomato lapses so this other jobs life time is shorter than the lifetime of its apparent job and what's great it's actually go context also has this ability to create new context that we swore to light them with certain durations or deadlines so it's the same thing so really productive for these conservatives worked like a charm well so we edit like few more samples started looking more advanced as things and stumble through these problems of nesting concurrent computations and let's take a look at this problem a little closely what is it's called concurrent decomposition so sometimes you have to do things concurrently instead of sequentially doing one thing and then another you want to do several things concurrently this often happens both it front-end and back-end you know for latency for many are different reasons but every time you launch a job to do a concurrent piece of concurrent work for you you receive a job and these jobs are resources don't make mistake they're just like files it's something you shouldn't just lose because every Ronnie couraging consumes resources well it runs it's still Christmas memory it does something you can just lose it to let it go because what ever force you to create those jobs may get cancelled and constellation is absolutely pervasive like it happens in backend client just goes away you don't need this concurrent work anymore it happens in front end user has closed your frame you know it doesn't need a tremendous concurrent job anymore but these are resources you have to keep track of it to be able to cancel or close them when there are no one we need it so what do you do one of the traditional approaches is to create this kind of composite job and then add all your jobs to it and when you need to cancel all of them just call cancel on this composite object but I really urge everybody to never design a pill as that please the IP I mean it's really common pardon in varias aps I've seen a dozen sometime but I ordered from this stage if you ever go to design some new API that works please don't force for programmers who use your page do something like this it's really cumbersome takes lot of code it'll error-prone it requires lots of oil-free to maintain all those composite whatever things that you see all over different resource lated api is in our modern world there is a better design pattern that's an officially called lifetime partner there was the reason why we originally called our job prototype a lifetime and for this people in this lifetime part on all you need an object that lets you register a completion Handler and we already had this object a job a job lets you register a completion handler it can be cancelled so with this job in hand it is simple to function interface instead of a composite job a separate object separate class we can just use this job as our composite and instead of returning a job in having to add them to this composite we just pass a job to lunch function and eat what it does is adds itself as on completion listener to cancel itself when the department is cancelled and the nice thing is it job is current in context so we can launch all of the day's recurring context parameter in our prototype so we didn't even have to afford a special parameter in our curtain builders like launch to support it it just works out of the box we just call job cancel and it cancels everything that was started here like the dreams coming true but not exactly because in this way job is just a different name for consolation talking that we wanted to avoid from seashore I've said that f-sharp does better it does implicitly propagate this consolation document forcing programmer to do so we wanted a better solution that does not become an explicit consolation talking but what they have kind of solution we have this context propagation and what is that you see any suspending function and Kotlin receives curtain context from its color so what we had to do is add a simple feature to our compiler standard library to let this function explicit to refer to this country so we added this curtain context property that lets me refer to the context I'm running it and this way I can say launch in the parent curtain context and it works I don't have to explicitly pass the context a job I can refer to implicitly past one great and it even works in even nested fashion so I can launch a curtain that itself launches to other children everything is propagated in any depth grid I also propagates execution context because I capture the whole context everything in this including job and you know the word to execute the curtain it's even better I have to say I'm running it in my UI thread in just one place in the root of my hierarchy name is drew dreams coming true but there is one nagging problem here what's how do we handle errors in our concurrent decomposition and this is really a serious problem when you start anything concurrently interesting while is contrasted to serial execution so when you could think serially I do one thing and then another for say hello then say world if the first one fails then in language like Kathleen c-sharp other languages with exception it's just our exception in languages like go each returns an error code and I return explicitly but anyway I don't think is acute the next line let's say this one fails that usually that's it no further execution and that's easy this error becomes there of the whole job but what if I do things concurrently now I say hello and world concurrently this can fail and when it fails it actually cancels its job with the corresponding exception and because this job is parent of the child of this outer job this my outer job will get canceled just like in the original so I mean now I have an error my this is my failure it was canceled with this exception but the problem is the other one is still running it could still fail it will also try to cancel a parent job with the different exception and they can feel like really concurrently really at the same time they both so there's no like way to say oh if one fails I immediately stop the other but I may be too late the other might have already failed because they really two concurrent things so what do you do when you have this concurrent errors now instead and there is not much room for choice but there's one solution to know whether the job has succeeded or failed I have to really wait until all my children complete it's not enough to say oh the first one fails I'm failed I have to wait what what other failures are I have to wait for everything to shut down normally or abnormally to know what will happen and this leads to a real job that we have now in cotton the real job that we have is quite different from the simple prototype we have it's not it has it used to have two states in prototype now it has way more states because in provisions for these error handlers in ours where I can start completing but I can still fail or I can be canceling but you know others children have not completed yet so may also fail in contribute their error information to the overall error that will be the result of the overall execution so and we have to change our builders so that this curly braces after the lodge they may not just denote the scope where I can launch something concurrently but they also explicitly wait until all the children to complete but let's take a look at a little bit more abstraction things you know I rarely write code like this or sometimes I write usually in larger software we'll use lots of abstractions in the key abstraction method in cutting and frankly many other languages is function so I can say okay I do some two launches here let's extract it to a function so I have a function of say hello world and this function actually launches two concurrent processes so we'll five you know edit a little bit more section in this code but we can still have a failure here this one can fail but when it fails it had captured the parent context so it will cancel this job but interesting even though the parent job is canceled the function itself may still which are normally so within a really strange world where a function kind of now has to exit path you know it can exit normally but as a result of who work produced side-effect of canceling sparing job this really hard really hard programming models will it blows people on mine so we have to do something about it and the solution was this we have to add a function that delimits our concurrency that creates a new job specifically for launching this concurrent things and this curly braces they have to wait until everything in their scope completes and if there is any failure in any concurrent children processes then it will throw an exception normally so there is only one which pass for a function it is a resource normally or iterance with exception there's no other side-effects that function can produce and that leads to nice programming model like more useful to your programmer because now program is looking at this function secular world they don't have to read it source to see how they can use it they know like every other function can AZ which are normally of a always exception cannot do any other spooky side-effects so this kind of encapsulate concurrent decomposition of this with sculpt prototype function serve as a way to encapsulate concurrency so that it does not escape to the outer world but looks like anything else from outside so project was good I mean it worked but it suffered from two serious problems one problem it was error-prone because nobody forces me to write this way scope I can just forget to write it and it still compiles but it starts doing these spooky things it's affecting doing some side effect on somebody else's scope somewhere way way up the stack and it's very boat you know in the first so I did that when I did the first workshop about cotton curtains more than two years ago I still had a prototype like this it was pre-release time and I had to say in my workshop you know whenever you want recruiting always in here it pine cone always write it like this and then you know one listener said but why then don't you make it a default why I have to write it every time and this was like really fair observation like if you have like if you have a guideline like I said the beginning we require programmers do this and this every time that why you require programmers to do it like make it a default so the problems are not required to do it you know you can have compiler do it for them but how we do it and the solution fortunately relied on existing we did not have to change cotton language we used existing features of content language to have it so we want it like this and in order to have this we made those launch and extension function exemption functions this cotton think where you can it's also not just calling this also has shops modeling we just have it where you can extend some other object and say in the context of this object I can have this function and this scope would introduce this curtain scope object that and launch is an extension on this Kuragin scope so without curtain scope I cannot call lunch and we ended up because this object was called curtain we ended up calling this function curtain sculptor so that's a modern solution to this problem is how it's called not a prototype but that's how it's called now and it is really great because now you cannot remove this curtain scope from your code because it stops to compile there's no curtain scope and launch will show be read but you can do all sorts of other things you want to do with concurrency for example you can do a loop so this court in scope explicitly introduced by special construct because it's not bound to this any curly braces in the language because like any loop curly braces I want to do a loop and in this scope launched a number of concurrent processes using or any other control moreover I can use a traction I can say uh this launched I'm usually talking somewhere else I want to extract it into function and when I do it in cotton in my IDE it introduces this launch say is an extension on curtain scope object and now I because it's extension currency scope I would not be accidentally be able to call this somewhere where I have not delimited this scope for my concurrency and Willie you know that was really a solution we like but there was one missing thing and this missing think was a name okay so we name it so we look at we invented something new well it didn't seem like this like breakthrough like definitely other people have you good out and different there isn't name for you but what it is how it and it's like they think were like all-stars to club like it was beginning in middle of 2018 and we were about to finalize it this whole thing turned it from prototype into release and we needed a name and we needed to finalize this whole concept or drop it if it's like nobody else does it and nobody else will understand it and we stumble into this blog post is April 2018 and blocks course is called notice and structured concurrency or go statement considered helpful it's written by a nothing L Smith who were at the time on a trio concurrency library for Python and he stumbled upon the same problems and instantly came to the same kind of solutions and he got a really good name for it he called it structured concurrency if the reason and this is blog post is really it long weed but it's great because it explains why it's called structured currency he starts with showing the classic primitives concurrency primitives in different languages it shows go in going which shows thread craze the ones we go inspired it that's what we look to India design and he explains what's the problem with those primitives and he refers to the others great work from 1968 byte extra called go-to statement consider how from who had you read this work by the extra I mean I also will everybody to read this is this is I mean even though it's more than 50 years old it's so much relevant to the problem we're facing today because why there in the beginning he knows that the human mind can is well at visualizing static structures you know the but it's human mind is little hard at grasping processes things that evolved in time so in Dexter says we should strive to structure programs in such a way as to make this static structure of the program as closely possible model for what's going to happen with insurance in process and execute in time and it was extremely relevant back at this time in debate we do in structured and unstructured programming and it's even more relevant nowadays when we talk about concurrency and distributed programming what's the similarity and then we go to these blog posts by Nathaniel he shows it really nice graphical way he shows you see look at sequential execution it flow goes top to bottom you do one thing then another but in the past we had this go-to statement they could jump anywhere and that makes human hard to follow it how to reason about this code that was Dixie was arguing about and then structured programming came abroad a structured program introduced instead of a single go to introduce a number of constructs there are all different different purposes but they have one thing in common they all has their floor of merge at the end you know they do something but it is they merge so you can treat them as a unit you can observe them the way in your mind you know they can jump into random place but if you look at the state of thought or concurrency nowadays you know pthread create go other things that just launch a concurrent process you see its little similar to go to their floor looks like this you continue executing downwards but you also have launched something at the side that's now completely running completely independently and nathaniel argues that we should instead try for structured concurrency primitives that do things concurrently but the airflow control always merge at the end and that's exactly what we created the cart in scope that we define by that time was exactly this structured concurrency primitive and the launch inside this launches launches this concurrent processes in the all their flow all mergers at the end so now we had a name we it is structured concurrency and again the Nathaniel block was nicely somewhat structured currencies is that the parent has always to wait for children's completion and it gives you two nice properties one is resource cleanup remember those concurrent words are resources so we structured concurrently you can never lose the curtain but you can accidentally launch and forget about it because otherwise the parent won't complete there is no chance for excellent resource leak which tortured concurrency and there as you get error propagation you never risk to lose exception again and there was kind of one of the things people complained in the initial before we had structure can't concurrency caught encourages people said oh you know don't use it I mean you can easily launch curtain it's crashes with exception nobody catches it anywhere it's just lost not anymore we structured concurrency you can't lose an error anywhere because this always gets propagated to a parent that always waits until all their children to complete so seems like pervasive idea like Universal seems like it should be used everywhere and well let's see is it it's actually in fact is it's catching up it's appearing in other across languages and echo system cell just quick will give you few examples so first example of course Python methanol was working at the patent trio library and in history library it looks like this you have this construct called nursery this is what a curtains cover job in our world and this async width in Python it lets you scope execution and wait for everything inside at the end an inside you can do anything you can do loops for like in our current scope construct and start soon on the nursery is how you how we watch cartoons different names absolutely same concepts same approach to exception propagation everything even Java and Java you might know there is an ongoing work on project loom that aims to bring light weight concurrency to Java programming language and they're also looking at structured class a prototyping in one of the people who works on it sure this example that's it's not if it's just what they are thinking about it so we might have somewhere in Java something like fiber scope that's an Alec of curtain scope and using javis try you can encapsulate the scope make sure it's being weighted upon and inside you can launch which would be called schedule there and even go you know the goal there was kind of pinnacle of the Nathaniel's critic because he said I will just use go as a common name for the curtain launching primitives even go is the ED instruction concurrency primitives in the morning goal you'd find this very nice thing called ergo and make no mistake it is a structured concurrency primitive and that's the code I show just from the documentation page of this Arabic class so this actually is code and with this scope instead of just doing go and some code that's unstructured you can say g dot go with uppercase it's now a library function or the keyword it's launched it's a structured primitive that registers this as the children in this error group collects its errors at the end you can wait for the whole group completion again its goal you have to be explicit that's go style but but still even though like make no mistake even though it's like an explicit go style you have to write down everything you do meticulously it's still a structured concurrency this same approach the same primitive an actual though also talk now appearing online arguing that that's how you should do concurrency what is the only right way because it is structured approach to concurrency so so that's it so so we're next step its destruction concern solve problem we've released the library almost a year ago so it's kind of our API is set in stone now we can tweak adjust it but but basically the concept is there is released lots of there are lots of lots of usage for it what we do next what should be next go and the next would be of course getting rid of unstructured currency completely that's if you go and read a regional Dijkstra talk he did not talk about why you should do if while and for in your program language he was arguing that you should drop go to from your program languages he said that if we remove go to it will make our code easier to reason about and we gain additional benefits that was the argument and I will do the same argument we should start thinking about how we over time phase-out unstructured concurrency primitives or all the programming languages we use that should be the ultimate goal and it took very long time for structured programming to catch up we took dozens of years until from the introduction of structured constructs to the time where new programming actually dropped unstructured go to completely yeah we are the beginning on the same path with concurrency we're just at the bean we we have structured thinkers it's appearing we still have instructions that and even in the Kotlin we have not got rid of completely what we only did we said now launch is structured so we can enforce structure by default which is good it's better than being a structured by default but we still have this escape hatch if you had an old code legacy code and you want to use our custom carotenes and you don't know how to how to structure it in our world you can say global scope launch like we merely made it little harder to be unstructured we're having it removed it completely which is beginning we're just nudging people into this new structured world and you know I write this block boss say why you should not be using global scope it's just nudging it's like you know please don't do it be it be nice person you know be structured make sure your code is understandable to others you know which will work better avoid tons of different bugs and cetera et cetera that's my room it will still have it and our next step should be over time completely removing unstructured Congrats that's that the end goal the end game for it so that's the end of my story if you if you want to learn more by itself there's few pointers I'll give you first of all if you're interested in more details I mean I did know it wasn't talked about design of cotton cards yes it was just really short story of how I've committed lots of details so if you want to read in a full glory go to design document explains everything how can test propagation works what's the Spanky or does everything it's it's that's how this feature was integrated into cotton as a language you can also study the library guide that's what we're what we're prototype had ended with so the original prototypes they ended up in a library with all this launch curtains cover another library things that supported the library itself is open source an SSD cotton language itself it listen github you know you can check the source you can command it was again original idea that shouldn't be hard-coded into language like you you and you you should be able to clean your mind you with the own concurrency primitives this that you like you know we should not be forcing in a language what you should be doing which merely give you like a set of primitive tools to construct the things you want with it and isn't going work you know we're constantly working improve we accept issues we tweak things we improve performance and if you're interested we're hiring you know in our libraries and cutting teams their positions open so you interested come talk to me after the talk we're expanding team and there's a really little also working concurrency and all around it so that's it thank you very much for attention thank you for coming here questions still have five minutes do we have two questions thank you talk I have actually two questions first question what will happen or how a company will handle situation when for example you trying to call synchronized code function or code from a synchronous from co-routine for coordinates there's no magic so in cotton regular function they still exist so we don't and they work as efficiently as before so they're not change anyway so we don't have this you know if you if you if you came to listen to to to talks before about go scheduling you know you've noticed a go program language because it's like they have to take care that you know trade-offs between performance of regular code versus we don't have these trade-offs because regular are still regular they work at the full speed of Java Virtual Machine which is pretty efficient nowadays if for many work loss which is the speed of which of this bit of C code thanks to the workers of some great people who've seen in this audience here yeah so nothing changes you know your regular functions your mathematics seen as cousins and new heavy computation who still works the same it's only affects your networking code like things like our receive a packet then you have to send this request this and nowadays you have read a lot of this code it's always waiting you know you send message to us you have to wait to response that's the only this you mark this function we suspend and only they are affected it's only them that are part of this mechanism everything else work just like before thank you in a second question for example in Python we have some kind of event loop and what about coding do we have some kind of we don't have like implicit event loop is always there but this actually run block in that first issue is actually what creates Elemental so inside run block and then you can watch Kurt is that the bound to this event loop and they will all see so once you're in your main function say one block and you have created a mental it's just more explicit like Python every program has it in our case you have to explicitly run it and then you have it thank you the first question there is what you think is a Chronos go to that is considered harmful in case I don't know I mean it's hard to answer this in short again because I mean this paper that that's blog post I'm quoting it's it's really long so I mean if my answer does not my argument don't suffice and just I'll open it just go read it I mean it's really answers in full what's considered harmful is unstructured way to launch concurrent processes like these are shown on this page like pthread create a go or spoon or you know creating and starting a thread and that's all on structures this create and you flow in your code that does not terminate him or does something completely concurrently with the rest of your code it's hard to reason about its resources a if you leak it creates a potential that you lose exceptions creates lots of problem makes your code way harder to reason about just like go to statement deed 50 years ago in the programming languages at that past time because you know the go-to of the past is not the same go to as you have now in some languages like if the old times you can jump between functions you can do anything with go to nowadays even some ways that we can go to the routine is to limit a structured form okay next question let's consider the case when I have two different synchronous context one context is UI thread other context is it's your companions rate for example native and as I understand and second context is passed through the do when a a call from UI code network coder I need to create to create new york and text use the network context it when i originally from material but I have quality from your I can check see if you context is inherited when switch happens there are two ways to do it in in with with our libraries one way is we have a special function called with context so can explicitly ask to switch you can say with UI context do this and they will then wouldn't matter which contacts even before if you want in DUI contest you'll get switched and then return back that's one way the other way which is kind of more it what kind of a better way is actually use what go program language you know taught us to do use channels you can have curtains running separately in UI thread and you have separate curtains to run in the network thread and you have channels and you can communicate between them so instead of you know trying to call functions just structure your code as a number of sequential processes that are communicating this whole mindset is called CSP communicating sequential processes and it's yet another topic on how to structure code this way but it's really powerful for certain kinds of application
Info
Channel: Hydra
Views: 11,783
Rating: 4.9575596 out of 5
Keywords: hydra, hydraconf, kotlin, coroutines, asynchronous
Id: Mj5P47F6nJg
Channel Id: undefined
Length: 60min 1sec (3601 seconds)
Published: Mon Oct 14 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.