Think Twice Before Using Async Rust | Prime Reacts

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
the state of async rust holy cow in the middle of this picture let me I'm gonna move myself over a little bit the state of async runtime recently I found myself returning to a compelling series of blog posts titled zero cost Futures in Rust by Aaron Turon uh about what would become the rust or the foundation of Russ async ecosystem in the Tokyo runtime this series stands as a Cornerstone in writing about rust people like Aaron are the reason why I wanted to be a part of the Russ community in the first place uh Aaron's the guy that did the whole Tokyo stuff and all that right it's pretty base pretty base guy right there well 2016 evokes nostalgic memories of excitement and fervor surrounding async rust my sentiment regarding the current state of the ecosystem are somewhat ambivalent through this series I hope to address two different audiences newcomers to async rust seeking to get an overview of the current state of the ecosystem library maintainers and contributing contributors to the async ecosystem and hope that my perspective can be a basis for discussion about the future of async rust okay the first article or in this first article we'll focus on the state of async rust runtimes their design choices and their implementations on broader rust async ecosystems one true runtime An Inconvenient Truth About async rust is that all that libraries still need to be written against individual runtimes writing your async code in a runtime agnostic fashion requires conditional compilation compatibility compatibility layers and handling edge cases uh yikes it's one of the problems about not having see this is one of the problems about just like having the community Implement things is that yes it's good because you get you get it's faster you get to see all the different ideas come out you get to kind of see and feel out every single different way things can be done and you don't have to make bad decisions in early rust or create things that are not good stop with the golden kappas stop flexing that I don't have one but the problem then becomes this right here which is now we have a bunch of different ones what do we do now kind of sucks uh executor coupling is a big problem for async rust as it breaks the entire ecosystem into silos documentation examples for one run time don't work with other runtimes moreover moreover much of the existing documentation on async Rust feels outdated or incomplete for example the async book remains in draft with Concepts like Futures unordered yet to be covered there is an open pull request though oh lovely uh that leaves us with this with a situation that is satisfactory for everyone involved sorry this delicious smoothie is making my mouth water I sucked that one dry we sucked them drive right there fellas that leaves us with the situation that is unsatisfactory for everyone involved for new users it is a big ass to navigate this space and to make future-proof decisions for experienced users and Library maintainers supporting multiple runtimes is an additional burden the it's no surprise that popular crates like request simply insist on Tokyo as a runtime uh this close coupling is an a known issue which is acknowledged by the async working group this closed coupling recognized by the async working group has me worried about its potential long-term impact on the ecosystem the case of async standard async standard was an attempt to create an alternative runtime that is closer to the rust standard Library its promise was that you could almost use it as a drop in replacement for the standard Library I have spent so many I I genuinely spent so long I don't know how long it was but it was long in my head trying to figure out why one of my TCP streams wasn't working whatever it's because I was using standard instead of Tokyo and it was emotionally bruising and it's like it should be so simple but when you're first learning rust and all these differences and everything named the same and how you know sometimes you get those Auto Magic Imports and all that when you're very first learning you can spend an enormous amount of time trying to figure out what's going wrong okay this was a long time ago but still I still remember it that was like my first big this really sucks moment uh take for instance the straightforward synchronous file reading code Bam Bam Bam Bam Bam okay beautiful an async standard uh it is let's see it is an async operation instead okay Bam Bam Bam Bam the only difference is the away keyword function coloring people we talk about that a lot here well the name might suggest that async standard is not a drop in replacement for the standard Library as there are many subtle differences between the two it is a it is hard to create a runtime that is fully compatible with the standard Library here are some examples of the issue still open new threads Bond okay yep there you go it is an enormous effort to replicate the standard library and it's not clear to me if it is worth it even if it were a drop in replacement I'd still Ponder its actual Merit rust is a language that values explicitness this is especially true for reasoning about runtime Behavior such as allocations and blocking operations the standard the async standard terms are team's proposal to stop worrying about blocking was met with harsh Community response and this doesn't feel very harsh I'm not going to lie to you is this why rust is filled with a bunch of babies harsh feedback I don't actually like if you really think about it when you reference the future standard of the project I really like when you check out these feel I I really do feel like we shouldn't be approaching this topic I really do think we should be concerned about it in my opinion I feel like these things man that was harsh this seems like somebody put some thought into it and thought about why we should be worried about these things as of this writing there are 1754 public crates that have dependencies on async standard and there are companies that rely on it in production however looking at the commence commits over time uh it essentially abandoned and there is no active development anymore ah this looks like grunt this leaves those reliant on async standard API bet uh be it for a concurrency mechanism extension trades or otherwise in an unfortunate situation as there is a case for Library developed on top of async Standards such as surf the core of async standard is now powered by small oh so small but it's probably best to use it directly for new projects again you leave the community to solve it this is what happens have you seen JavaScript tools grunt gulp webpack snowpack parcel Vite turbo pack those are like the big ones that I know about I'm sure there's other ones just saying you leave it to the community you get sub fractured you know you kind of you have to make this Choice Tokyo stands as rust canonical async runtime but to label Tokyo merely as a runtime would be an understatement it has extra modules for fsio net process and Signal handling and more that makes it more of a framework for asynchronous program than just a runtime parsley this is because Tokyo had pioneering role in the async rust it explored the design space as it went along and while you could exclusively use the runtime and ignore the rest it is easier and more common to buy into the entire ecosystem yet my main concern with Tokyo is that it makes a lot of assumptions about how async code should be written and where it runs for example at the beginning of the Tokyo documentation they State the easiest way to get started is to enable all features by do this by enabling the full feature flake this seems like a great getting started guide to me hey you don't know a lot about it just do that just do that what is that cargo ad Tokyo features full right it's just a really simple getting started situation like I get that I'm on that team you know you don't want to explain like a bet this is one of the problems about rust in general is that they want you to know everything before you program anything and so it's just like do you want to be the person that has to know everything just to use async or do you want them to start off with maybe overkill for sure for sure you don't need all these features start Overkill pare it down to me that just seems natural that's like that's how I like to learn is that I like to learn by simply you know being ignorant of everything and then slowly peeling back the layers you know what I mean damn I'm late you're not late you're not late by doing so one would set up a multi-threaded runtime which mandates the types are send and uh static and making it necessary to use synchronization Primitives such as Arc and mutex but for all for all but the most primitive app or trivial applications the original sin of rust async programming is to make it multi-threaded by default if premature optimizations is the root of all evil this is the mother of all premature optimizationed and it curses all your code with an Unholy Send Plus static or worse yet send Plus or send plus sync plus static which just kills all the joy of actually writing rust it was not Pride it was not greed it was Send Plus sync plus static that truly was the original sin I think it's funny and then God cursed the Earth with archview Texas everywhere arc mutism Arc mutasies okay usurk you pretty much now Zerg Rush are communities uh anytime we reach for an arc uh Arc or a mutex it's a good idea to stop for a moment and think about the future implications of that decision you know every time I write an arc mutex I sit there and think to myself ah I'm watching performance go away well I guess all of my multi-threaded just is becoming shittier like that's what I think about the choice to use ARC or mutex might be indicative indicative of a design that hasn't fully embraced the ownership and borrowing principle that rust emphasizes it's worth considering if the shared state is genuinely necessary or if there's an alternative design that could minimize or eliminate the need for shared mutable State this also highlights a really impressive thing about rust which is you just have to think a lot while programming you know what I mean like you have to think a lot have you ever thought about this in go what no like every now and then you Gotta Throw mutex around something but you really just don't you just don't think about these things which can be really nice uh and the same with JavaScript obviously you don't think about in JavaScript because well let's just face it it's JavaScript you don't think about it at all you know what I mean I avoid channels so they use like five locks interesting are there more efficient channels uh the problem of course is Tokyo imposes this design on you it's not your choice to make beyond the complexities of architecting async code Atop The synchronization synchronization mechanisms that carry a performance cost locking means runtime overhead and additional memory usage in embedded environments these mechanisms are often not available at all multi-threaded by default runtimes cause accidental complexity completely or unrelated to the task of writing async code say in general that I I dislike async rust every time I do anything beyond trivial I get a little pissed about it maybe after reading this I need to rethink my stance on async rust in general and maybe I need to just try a little bit harder to think about it in terms of like my own threads or use something like Cross Beam or small or whatever the other one is maybe I need to kind of bring it down a little bit and think differently about the problem yeah and then or just use gnu parallel I think gnu parallel is incredible I use it all the time whenever I can however now I have little hope that the rust Community will change the course on this point Tokyo's Roots Run Deep with the ecosystem and It Feels Like For Better or Worse we're stuck with it in the Realms of networking and web operations it's like it's likely that one of your dependencies integrates Tokyo was actually very true runtime effectively nudging you towards its adoption tungsten Knight Tokyo tungstenight at the time of writing Tokyo is used by 20 000 crates that's a lot other run times going Beyond Tokyo several other run times deserve more attention small a small asynchronous run time which is easy to understand the entire executor is around a thousand lines of code does it require like what does it I mean do all these ones somehow avoid the send sync static problem these runtimes are important as they explore alternative paths or open up new use cases for async rust drawing on a parallel with Russ error handling story The Hope is that competing designs will lead to a more robust Foundation overall okay that'd be great especially iterating on smaller runtimes that are less invasive and single threaded by default can help improve Russ async story I mean I like this idea maybe I just need to explore them all I guess I've always just been a Tokyo Andy does that just make me a Tokyo Andy is that what that does am I just a Tokyo Andy I just simply use Tokyo for all my async needs and I really haven't tried much else I think I download a Cross Beam once why is he calling them runtimes because they're run times you can tell what it is you can tell it's a run time by the way it is all right regardless of the runtime choice we end up doing part of the Colonel's job in user space if you allow me to play on Greenspun 10th 10th rule any sufficiently advanced async rust program contains an ad hoc informally specified potentially bug written implementation of half of an operating system scheduler modern operating systems come with highly optimized schedulers that are excellent at multitasking and support async IO through i o urine and splice they should make uh they should make they should make better use of these capabilities let's finally address the elephant in the room threads with their familiarity present present a path to make a synchronous code faster with minimal adjustment for example take our sync code to read a file from above and put it into a function there we go oh look at that box dying error boxdine air this is the first way I ever handled heirs was boxdine air it's also the way I hated my life you know like that's my first major program the drum machine on Twitch with rust box down air everywhere we can call this a function inside of the new Scopes thread okay there we go we get a little thread we get a little scope we do one of these read some contents we got another content we got another content look at all that content no join threads get joined automatically once the scope ends oh nice okay cool that's nice that code uh looks but like but I assume scope spawn are what does this mean are these what is this like are these their own threads are these operating system threads or are these some some sort of green thread I assume they're operating system level threads you don't really necessarily want to do operating system level threads right they're OS threads I assume they're OS threads yeah they're OS threads whose lifetime is limited by the scope they're created in okay yeah I mean that's really expensive still right uh that code looks almost identical to the single threaded version notably there are no await calls okay they get fair fair uh where read contents par uh part of the public API it could be used in both async and sync callers eliminating the need for a synchronous runtimes async rust might be more memory efficient than the than threads at the cost of complexity and worse ergonomics as an example if the function were async and you called it outside of a runtime it would compile but not run Futures do nothing unless being pulled correct this is a common foot gum for newcomers I have I have done this you know what the worst part is is when you try to ignore an error because you look at this right here and it's an error right so you look at the function's content as an error so you go underscore equals read this like you just want to ignore the error you don't care but what you don't realize you did is you just underscore equal the future and therefore it never runs and you have no idea that that didn't happen and it takes forever to figure out why things it's it's a painfully slow process to figure that out right in recent benchmarks async Russ was 2x faster than threads but the absolute difference was only 10 milliseconds per request to put that into perspective this uh this about as long as PHP takes to start in other words the difference is negligible for most applications I'd really like the challenge that one because I can't imagine that's true right because I can't can you really just spawn off OS threads that easily and it really only adds just a little bit of time that is that true a good PHP roast very eight yeah 10 milliseconds is a huge amount because you gotta remember when you have like a constellation of micro services it grows yeah I mean we just read Java Java said it was about two megabytes per thread PHP has completely different uh use case to rust this is correct 10 milliseconds is massive it is massive all right thread based Frameworks uh like the now inactive iron showcase the capability of effortlessly handling tens of thousands of requests per second this is a further complemented by the fact modern Linux systems can manage tens of thousands of threads tens of thousands of threads per second is is is it's kind of like is peas for rust I mean node bun on an empty request does like 80 or 90 000 or whatever on my local machine I don't know what that equals rust doing it like if I take bun create a server that just Echoes back a post body for whatever you send it right create an echo and just do that I can get it you know pretty high up you know not a hundred thousand but pretty high go is like a hundred and eighty thousand uh on my this is all my machine all local testing so again grain assault uh and then rust is like 200 and some thousand so you know when I see tens of thousands I don't think oh wow right like is there a big difference stop with your golden kappas oh we already looked into a project Loom all right turns out uh computers are pretty good at doing multiple things at once as an important caveat threads are not available for fee uh or feasible in all environments I'm not not by the way I'm not knocking this I just I don't have any data on whether this is worse or better I'm just curious if it is actually better or worse as an important caveat threads are not available or feasible in all environments such as embedded systems my context for this article is primarily conventional server-side applications that run on top of platforms like Linux yep just Linux uh I would like to add that threaded code and rust undergoes the same astringent safety checks of as the rest of the rust code okay fair it is protected from data races null dereferences and dangling references ensuring a level of thread safety that prevents many common pitfalls found in concurrent programming since there is no garbage collector there never will be any stop the world pause to reclaim memory traditional arguments against threads simply don't apply to rust Fearless concurrency is your friend Fearless concurrency oh we got a tweet we got a tweet people concur ANSI is it antsy or ANSI I always I always forget this one is it NC or antsy ANSI antsy not antsy antsy Fearless concurrency and ship it to production ship it ship that one ASCII JS is a religion so is rust so is all programming languages hello privacy what did I miss not a lot we're about to go to the last one all right let's see and if you need to share State between threads consider to use a channel I've never used much for channels I do want to use more Channel stuff I feel like there's a lot of cool things you can do I really think it's cool that you can break from a loop and return a value in Rust so you could have like a Tokyo select in a loop receiving values waiting for something to happen from multiple different sources and then when you get the thing you need you can return it via a break out of the expression I always thought that was pretty kind of clever you know I always thought that was pretty dang clever and I just don't I don't think about that enough you know what I mean uh my original intention was to have uh to advise a newcomers to sidestep async arrest for giving the ecosystem time to mature however since I realized that this is not feasible given that a lot of libraries are async first and new users will encounter async rust one way or another and cry an acrust truly truly cry in async Rust instead I would recommend to use async rust only when you really need it just learn how to write a good synchronous rust first and then if necessary transition to asynchrust learn to walk before you run fair fair if you have used asynchrust stick to Tokyo a well-established libraries like request and squeal X in your own code try to avoid async only public apis to make Downstream usage easier oh this these are actually all really good pieces of advice this is actually a great advice right here however it's valuable to know that there are alternatives to Tokyo and that they are worth exploring one hard part though is that if you have a thread running and it blocks because it hits a Sync API that you don't realize is sync for a long time you can get some goofy results in Tokyo right like some things can happen that you may not be expecting and it can be uh it can slow your program down a whole bunch it can block things uh it's not necessarily as straightforward as as just simply go you know uh however it's valuable to know that there are alternatives okay yep at its core rust and its standard Library offers just the absolute Essentials for async await the bulk of the work is done and creates developed by the rust Community we should make more use of the ability to iterate on async Rust and experiment with different designs before we settle on a final solution in binary crates think twice if you really need to use async uh to use async it's probably easier to just spawn a thread and get away with blocking i o in that case you have a CPM a CPU bound workload you can use rayon to paralyze your code rayon is pretty good uh I've I've played around with it if you don't need async for performance reasons threads can often be simpler alternative Fair it's fair really just threads and channels I think I just need to use just use those more but I will say that the go go supporting Syntax for channels and how channels work is massively easier the fact that you have to have a single read and multiple rights and you got to clone things around and all that I feel just like it makes it harder you know isolate async code if async is truly indispensable consider isolating your async code from the rest of your application I never know how to do this it leaks it's very very leaky keep your domain logic synchronous and only use async uh for i o and external Services following the guidelines will make your code more composable okay okay okay okay and accessible and on top of that the error messages of synchross are much easier to reason about facts facts upon facts fax that in the machine async rust feels like a different dialect significantly more brittle than the rest of the language I still don't know what pin is uh the default mode of right for writing rust should be synchronous freely after a stress rep inside rust there are uh there is a smaller simpler language that is waiting to get out straw strap uh BR is this Bjorn Bjorn made a little uh a little little post it is a language that most rust codes should be written in I actually really like this this was really great it definitely makes think more because I just reach for async rust first I I reach for async rust first and I don't necessarily consider its implications you know what I mean I just grab it and I'm so it's almost second nature exactly like when I start a project I I it was a very balanced article this was a very this was a tremendous one hey Cora corrode appreciated this this was this was this was a beautiful article um async rust is really difficult and really bizarre and I think I reach for it and I'm just so used to it and I program a certain way to it that I think often I forget maybe there's other ways and maybe I should not reach right away for async rust maybe I need to just try spawn in some threads and start using channels I'm gonna try that next time honestly I'm gonna try that next time next time I do anything I'm just gonna try to do uh uh I'm interested try spawning and tossing out something different I feel like I'm pretty good at rust I'm okay at async Russ pretty good at rust I don't know the deeper size right I call myself a level one developer meaning that like I wouldn't be able to effectively write Tokyo well right I don't know async rust down to its core and how it's actually done I just know how to use it I'm level one deep I know how to use everything I don't know how it works at a deeper level whereas like something like typescript I know at like a level two I could write pretty much any Library out there I feel completely confident in it I don't think I have a lot of I don't think I have a lot of problems with it um go I'm like a 0.5 developer I think I could be better I just haven't done a lot I just haven't done enough production level go you know what I mean I just haven't done that yeah I feel like I can do lifetimes I don't feel like I'd have a hard time writing like a really Performance Based library with no copying in all lifetimes I just don't because I just clone you know what I mean I just I just clone because I don't care I don't care for most the times most of the times I'm just trying to get the thing correct and make sure I like what I see because rust is one of these languages that it requires a different feel to really be good at it's different than other languages like generally when I'm programming go or JavaScript I can kind of just I can mostly just kind of do the thing but rust you kind of got to take a slightly different approach to it's just I don't fully have the right everything first try with rust yet I think I just need to do it a little bit more you know I gotta get there it's a take a step back language but I don't I don't believe in take a step back languages I really think that that's just experience I don't like the idea of taking a step back either I really I think that it's you should just be able to free write ejaculate code at high speed and get somewhere that means you've learned a language sufficiently and I'm mostly there with rust I can mostly just rage program rust but I'm not quite there huh whiteboard masturbation first so I never do whiteboard masturbation I'm not a big fan of whiteboard masturbation I don't like to I don't I don't generally I think it's uh I think it's I think that the more you plan out a program besides for the High bits I think often you don't get anything out of it you've just wasted time Zig I'm definitely not good at Zig Zig I'm like point one oh camel I'm like point one you know I just need an excuse to say masturbation okay fair anyways uh let's go marker uh I need to come up with a better name of uh of this title what should I call this this thing because the state of async rust run times is actually really misleading to what this article is about Dr Watson ejaculates 11 times in the Sherlock Home stories that's the strangest top fact I've ever heard the name is the think twice a gen
Info
Channel: ThePrimeTime
Views: 52,672
Rating: undefined out of 5
Keywords: programming, computer, software, software engineer, software engineering, program, development, developing, developer, developers, web design, web developer, web development, programmer humor, humor, memes, software memes, engineer, engineering, Regex, regexs, regexes, netflix, vscode, vscode engineer, vscode plugins, Lenovo, customer service
Id: TZxxWXVnb1E
Channel Id: undefined
Length: 28min 29sec (1709 seconds)
Published: Sun Oct 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.