Why I Chose Rust Over Zig

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
why I'm not ready to switch to zigg from rust you know this Pekka fella okay I don't know about this peka fella and I don't really understand this photo why it has anything to do that I'm not going to lie I love programming and C he is a Linux Colonel contributor so probably not uh probably not too much of a surprise that the man loves C which is why I'm surprised he doesn't love zigg I know it's a little bit irrational but programming and C just feels right perhaps that's because I did spend a lot of time with c as I contributed to the Linux kernel those were good times because I had the opportunity to learn from some of the best C programmers in the world hacking on the Linux kernel also taught me the connection between C programs and the Machine code it compiles to which I guess influenced my thinking Pekka built differently confirmed I dude I'm so I I know he's going to explain to me but I just if you love C the the love of rust feels confusing okay the love of C feels confusing if you if and the love of rust however C is an unsafe language it's easy to make mistakes but I spent so many hours on debugging C programs that at some point I ended up being reasonably good at it classic do something long enough and you get good at it I was often able to uh Trace back what happened just from the Linux kernel register dump or oops as they call it uh and fix a bug that I was not able to reproduce I also learned to write C in a way that minimized the mistakes I felt productive with C type one in the chat if you are the same way do we have have any c Chads in here do we have any do we even have a singular C Chad in here we have a lot of people typing one and I just doubt it I'm doubting seriously there that there that many C Chads in here segmentation fall C is also a low-level language when you're programming in c you end up writing a lot of code just to do the simplest of tasks there are no built-in data types so I washed so I wanted a hash table or a linked list I usually ended up rolling my own I and I almost never used a binary search tree because writing one yourself took forever to get right so perhaps C wasn't perfect after all H it is true hand rolling your own bin your own binary search tree is actually very difficult especially when you consider uh deleting uh deleting nodes like that's it's it's just a it's a lot of effort to get correct cuz the amount of little things you have to get right in a binary tree and all the links you have to touch it's it's a lot of work balancing is the worst yeah yeah like if you do uh AVL for balancing or red black for balancing dude I can't even understand red black that well like I have never I've never done red black in a full implementation I've only done AVL in a full implementation red black is fun and maybe one of these days I have to implement a red black tree cuz I've only ever done AVL I thought AVL was a lot of fun the world's balances on the most fragile things and balancing binary search trees is most certainly one of the most fragile activities of all time uh red black trees are just binary trees and they have like three rules for balancing not hard yeah I'm sure it's not hard I know know it involves like when you have a black Uncle you got to do something but I can't remember anything beyond that like that's it that's all I can remember about a red black tree see if your nod's uncle has a red color then change the color of the nod's parent and the uncle to Black and the grandfather to red color and repeat the same process for him grandfather if grandfather is root then don't change the grandfather's red color like there's a whole set of rules you have to go here people just because you don't just because you don't understand red black trees okay it's showing it's showing you don't know red black trees right now I did end up writing quite a bit of C++ professionally on two different occasions the modernization effort that went into C++ 11 and subsequent versions made a big difference now you had access to a variety of data structures and algorithms and with things like classes and templates you ended up writing much less code but C++ inherited the unsafety of C which meant you still got to spend a bunch of time debugging your code okay skill issues so in other words it's easy to get skill issued absolutely rust memory safety and complexity when rust appeared in 2015 I was really drawn to its promise of memory safety and then you got absolutely owned by async I had done by the way in 2015 rust was much more rough just use Smart pointers uh I don't know when smart pointers uh were exactly implemented I want to say smart pointers were in 2011 but I'm not sure if they were uh ason yeah yeah most people just did ason of course that's how we did it right uh whoever just said that someone said ason yeah just do just do sanitizer address sanitizer stuff and that usually does it uh C+ plus had Auto pointer yeah most people just did did that did that uh at least that's what we did in Netflix caught some of my bugs I had in my uh memory analyzer was in uh using that that uh Val grind yeah I did some Val grinding for sure I had done some hasal programming around the time and I felt that both languages although designing for completely different use cases shared the if a compile Works mindset I've always hated this mindset because it's just not true and what I mean by that is that there's invariance within your program I mean all my toughest bugs are not are are logic bugs I called it I know I've I've I've never liked this rust mindset and I don't understand how this rust mindset has proliferated proliferated this long right like you build anything that's sufficiently complex and your worst bugs have nothing to do with uh ownership or with one person uh mutating it's almost always some other thing and this is like this is a very common rust mentality and I and I guess a hasal mentality as well I just don't really like it the fact that the borrow Checker would be able to eliminate a class of issues that you encountered and see all the time felt magical yeah fair fair you yeah I mean I will agree with this uh the fact that for those that don't understand how rust effectively works it's really really simple um it's it's it's very very simple uh by the way someone's saying that the worst bugs are race conditions perhaps their rise conditions but the bugs on average that I encounter have nothing to do with rise conditions the bugs that I encounter are simply me not understanding how things change over time um anyways how rust Works in its most simple form is that you have to understand the difference between the stack and the Heap everything is allocated onto the stack now there are Pointers into the Heap when your stack item goes out of scope drop gets called on on it which means that if you have a function and in it you allocate something say a string which allocates to the Heap you're going to have a stack item that's going to be a fat pointer that's going to be the pointer plus the length effectively I'm sure and I'm sure there's one other item I'm sure there's like capacity or something like that as well I'm sure there's like some other thing when it comes to the capital S string that I don't know about but whatever it doesn't really matter and when this thing leaves scope drop gets called and this gets dropped along with the pointer to the Heap gets dropped meaning it gets freed so in other words this thing gets you know it's very easy to call free on items cuz you don't call Free Yourself free gets handled by rust so that means there was a Malik called here for the string if you return the string then no free is called instead the free is then that stack pointer is then returned to wherever the calling is and then it keeps on going until its only stack reference gets cleaned up and then the free happens right Malik chills return yeah it happen so that's like the basics of rust for those that don't know what rust is uh there you go it's not it's not it's not that crazy and so this makes a huge difference when you're allocating and deallocating because there's a just a whole set of really shitty experiences when it comes to doing this but after exploring the language for some time I gave up because the tooling was changing all the time and quite frankly I could not wrap my head around the borrow Checker perhaps I was thinking in C too much I think if you think of rust as uh as I just explained it as stack and Heap honestly it just makes life really simple like if you think this way it's really really simple plus 2015 is much much different fast forward to 2021 I started working with rust professionally now I knew I didn't want to use C or C++ and globber my co-founder had good experiences with rust so I went with that I probably fighting let's see I was probably fighting with the borrow checker for two or three months until things started to click I was thinking and see too much uh I then discovered the send and sync traits and how they really help with multi-threaded programs the tooling and ecosystem has really grown up since 2015 absolutely rust 2015 versus 2021 is that's a vastly different you know vastly different experience after the initial learning curve programming and rust really became productive fair fair you know for those that don't understand how rust becomes really productive is when you when you first start off you start fighting something called the borrow Checker and you can't figure out anything and then what you realize is that if you are using just sync stuff you just call do clone and if you're using async stuff stuff you just simply hit it with the old Arc mutex and boom you're done rust e z that's it that's that that's it it's that easy rust is a complex language the more I write rust the more I feel that there is too much complexity when you use traits or async rust things start to feel complicated perhaps I'm still thinking too much and see I don't think you are I think it is complicated I think it is a complex language what is an AR mutex well Arc stands for Atomic reference counting meaning that it has that same stack-based allocation except for that stack based allocation has a pointer to the Heap where the thing is stored and it has a counter and that counter is an atomic int not just a regular int so when this thing gets dot cloned this counter goes up by one when your stack variable gets removed it gets dropped this count goes down by one when it reaches zero the pointer to the Heap is then cleaned up it's like it's it's it's pretty straightforward right like it's a pretty straightforward thing right uh and a mutex is just a semaphore of length one easy you didn't know that what are you a loser yeah welcome to the '90s yeah welcome to the '90s everybody shared pointer then yeah it's literally a shared pointer and mutex is a shared pointer so it's shallow clones yes uh clones clone the stack remember that when you call do clone it usually clones the stack except for in Rust rust is a little bit more confusing typically you clone Stacks you don't clone heaps in Rust you clone Heap or stack depending on the on the data structure again this is why I say that rust is generally a complicated language because you need to understand when something clones the stack versus clones the Heap right so an arc clones the stack not the Heap if you do string. clone you clone the stack and the Heap right it's a little bit yeah it's it's a little you just have to have all these kind of you have to have all these like rules in your head to do effective um effective effective uh rust all right Zig as a modern C I think sometime in 2022 I discovered Zig because of two projects bun and tiger beetle by the way bun Jared will be on the stream here shortly in uh 48 minutes Jared's going to be on the stream and uh joran was supposed to join us as well but joran did not uh as had done with rust in 2015 I started to explore it I quickly discovered that I really like Zig because it feels like C it is it literally does feel like C but just with uh but just as rust after initial exploration I gave up on it because the tooling kept changing all the time and the ecosystem just wasn't there for me I do agree Zig ecosystem is probably the worst part about Zig is that uh it's just like the tooling just really ain't there yet and the ecosystem isn't fully flushed out but I really it it it's it's still a great great language in the summer of 2023 I wanted to give Zig another chance partly because globber would not shut up about it I also perhaps may have been hounding them about how great Zig is um I decided I would write a small proof of concept a clone of squeal light in Zig as I started the work I discovered that Zig is a low-level language not lowlevel in the way C is but much lower level than rust but I figured that's acceptable price to pay because Zig just feels right as I was working on a database I needed a way to perform IO efficiently I was reading the tiger beetle source code and then I discovered Michelle's lib X EV is this like a lib UV style uh and even contributed to it a bit but after three months of weekends hacks I ended up converting the code to rust I just felt productive again now the real question is did you feel productive because you're writing full-time rust all the time you're writing rust for your entire workday like I mean the hard part about that is feeling productive is difficult and I think Pekka will agree with this one he'll agree with this take if Monday through Friday you are writing an X and then on the weekends you write in y x will always feel better right like X will always feel better because you're just used to every last bit of it it just that's just how it works you can't you cannot help it because weekend hours are much much smaller wrong oh camel my camel shut up TJ uh so there's like definitely that as a thing also when you start using rust a very weird thing happens you approach problems the rust way right you want to use enums right you love some some types you love the idea of traits right you like you adopt a lot of very Rusty way of doing things very okay A has way of doing things and you just start to uh you get kind of like stuck in a mentality and it's hard to undo this mentality just like if you work with go a lot it's really hard not to try to use interfaces for everything it's just because that's what you're used to doing and so then when you start using interfaces for everything and then you go to a language like Zig that does not have interfaces you find yourself you know you find yourself hurting uh why am I not ready to switch to Zig just yet so why did I end up ditching Zig in favor of rust although I still like Zig a lot for uh starters comp comp time feels like a hack really crazy okay so we interviewed Chris lner yesterday uh by we I mean TJ and I TJ streams by the way uh uh comp time was something they modeled part of Mojo after this is probably irrational but I just don't like comp time very much in fact I would much prefer the Legacy pre-processor macros of C if I if I can't have generics really I got to know more more about this because this just just doesn't feel right like one thing that's so incredible and I talk a lot about this that I just absolutely am just completely blown away by if you go to zigg Lings and you look at just like the basics of this it's comp time here uh uh is duck I think is the name of it yeah this function right here right this function is a comp time function meaning it it executes during compile time so possible duck is an any type it doesn't know what's being passed into this and we go down here and we get the type of my duck this is done during compile time then I say does this type have a function or has a declaration called waddle does this thing have a declaration called quack if it has both a walk like a duck and quacks like a duck it is a duck and if it is a duck we call quack on it now here's the cool part if you go up here and you see these three different things they created they created a duck which has waddle and Quack they created a rubber duck which has waddle and Quack then they created a duct which only has connect they're able to call this function quack or is is a duck with a duck a rubber duck and a duct right and because it's compile time this generat three different functions it generates the rubber duck version the duck version and then the duct version and the duct version is just simply an empty function that does nothing other than returns true or false which is pretty cool because that means it actually compiled this reflection call at compile time like it it compiles it as opposed to running it during runtime like when you use go and you switch on types it's doing the switch on types and you have to do all this stuff at runtime whereas this does it at compile time which is pretty cool aren't macros also generating functions macros do not generate functions macros generate text wherever that whoever said that yeah there you go macros generate text when it comes to C so C just generates a bunch of text and that's it they don't generate anything other than they're just text Replacements that's it they're just flat text Replacements that's why when you have like an all capitals if defi or Define it just literally replaces word with number right uh Define true as zero this is literally possible you can do that uh you'll still end up chasing uh Sig EG uh I don't know if that was me thinking too much in Russ but I ended up writing lots of silly bugs that I that ended up in segmentation faults that I then chased with the debugger see that's surprising I actually got none of those and I think one thing that allows you to do that at least in Zig I have I've I've literally so far in my game that I've been creating I have I have yet to run across a single one and we have a decent amount of that I think one thing that makes that so I don't run into it is that whenever I do a game State all my things that could be nil I put a question mark in front of them and so when there's a question mark in front of them it means that I have to first check if it's nil or not and so by doing that intentionally I know that this cannot be anything but a potential null and so I have to like work through that every single time it like it adds all of that safety that I need when I need it if I don't need that safety then I don't have it right I don't have to have it because I know this pointer will always exist I assume this would get better over time if I wrote more Zig of course but I've grown to trust the borrow Checker yeah you you also end up leaking memory again this is probably me thinking too much in Rust but I ended up writing code that leaked memory all the time of course Zig has really nice tooling here to catch them quickly so perhaps not such a big issue yeah Zig is fantastic in this let me just show you a quick a quick version of this um since we're doing this uh engine test here I'll go here and see this I'm going to erase that one defer statement so I deferred the de initialization of my game state right so I'm going to just I'm going to do that and I'm going to go Zig build test I may have a bug please don't have a bug please don't have a bug there we go one leaked so it's showing me that I have a leaked item and it's even showing me where my leak was like look at this all these creep creates were leaked all these things were leaked and if you go to the very top of the original leak it's going to show you you leaked this thing right here Zig line 20 right here that was leaked so I'm like oh I forgot to clean up the game state I'm going to put that back in it's gone now right if I go up in here and I see this and I just take say I forget to like deit my Towers or how about this one I forget to deit my creeps individually but I deit my uh my creep data structure right then look at this it's going to tell me hey you've accidentally leaked three creeps right it's going to show me all the places that I leaked it right which is actually pretty cool I don't know I really like that like I actually really like how all of that works and I I find that to be a very comforting way to program and even if you run things into bug it lets you know when you've leaked stuff which I I think is a pretty good General experience for being very seike right there are no books on Zig I really really need a good technical book to learn a programming language but there are none for Zig okay that's actually this is super fair this is super ultra Fair uh I actually I find this to actually be the probably the most compelling reason not to use Zig right now besides for Tooling in contrast there's a lot of great books on Rust and specific topics on Rust available it just feels very hard to learn Zig completely fair you want to you want to learn uh async rust async Rust book right there you go here's the entire book of everything that has to do with async rust right like that that that makes sense that's this is probably the most fair thing right ever uh ecosystem is perhaps not there there are two large Zig projects bun and tiger beetle well now there's ghosty as well so he doesn't know that ghosty is also if you don't know ghosty ghosty is Hashimoto's terminal and they are great source uh and there are great source trees to learn from but there does not yet seem to be large ecosystem to tap into like there is with rust tooling is also perhaps not there the tool chain Zig itself provides is great but it keeps changing a lot like rust back in 2015 but more importantly third party tools like GitHub co-pilot I feel like uh this sentence was forgotten but more importantly third party tools like GitHub co-pilot something yeah co-pilot just doesn't do really good with Zig because it doesn't I'm surprised that Pekka you you know actually Pekka using uh co-pilot it was is actually kind of a bit of a surprise I thought Zig now has a package manager so we only need to wait six years for Zig to be awesome my guess is that within the next two years Zig will have a lot of the problems finished how do you npm install Zig not really sure industry investment is not there rust is used across our industry for me the Tipping points were when Microsoft started writing parts of Windows in Rust and Linux kernel added support for rust these two things alone mean that rust is likely going to stay around for a very long time in contrast zigg does not yet have the LI the level of Industry backing right now it do not mean that Zig won't eventually get there but rust is much safer and boring option right now can't argue against that one that's good good this is if if you are only looking for things that are um you know that have big industry adoption totally reasonable true true and true true true and true I feel like I don't feel like he gave any really good technical reasons though I feel like his I I I'm actually I'm a bit surprised that Pekka did not go more into this to me it seems like he doesn't quite understand comp time which is a bit surprising because Pekka might be probably one of the most talented Engineers I know of so I'm a little bit surprised by this Vibes were off with Zig that's how I do it I really really like Zig but I am not ready to switch to it just yet rust is not perfect but it's my go-to language for systems programming I feel productive with it Zig may be in the situation rust was in in 2015 and all it needs is more time but for me I'll be waiting for the first book to come out and then get back to it I Al I am also hoping that maybe they will dumb down the language for people like me and provide an alter native to comp time but until then I will remain happy rust station I mean you got to remember like I love comp time I'm a bit surprised on on the comp time Hate by him cuz I feel like comp time is like the inverse for me I feel like rusts generics they narrowing of generics through traits and wear statements and the difference between calling imple versus box and dine it feels like that is much harder to Gro and be really good at at all points than it is the other way around what is comp time comp time is code that is executed during compile time versus um versus runtime comp time is just metaprogramming like const expression and uh templates and C++ yes it is that's all it is very Ziggy uh surely I'm dumber than this Pekka fellow you are and I don't think Zig needs to be dumbed down I don't think zigg needs to be dumbed down either uh let's see when do you need comp time when you want to build a list of something or you want to do something example of comp time I already just gave an example but here's another really easy example of comp time uh here we go an array list an array list is a is this right here is a is a compile time function that goes in here and it returns a structure that has an allocator that does all the things it's needed to actually build the underlying array list functionality it has the initial capacity it has the DN it has you know like if you're in C and you want a list of integers and then you want a list of char Stars you know you have to build those lists individually instead this thing operates instead you build a list that operates over type T and so Zig I have an array list and if I want a tower list I create a an array list of Tower and now I have a type Tower list so this is a struct this is a struct that was generated at compile time now I have this Tower list and so now I can have my list of towers wherever that's at Towers yeah it's really unfortunate that you have to write it by hand every time instead of having a simple generics like go yeah but you can do much more powerful things than you can with go so it's like yeah go is really simple but that's because go doesn't have deep support for generics it has light support for generics and that's kind of nice right like I like go for what it's used for it's a great web language how does go handle generics very lightly on functions right all let's see cool kits call it comp time dummies call it structural macros C++ DG call it template magic there you go you get the idea tradeoffs yada yada yada yada y can you mix type arrays yes you have to use you have to use tged unions though right you have to use taged unions and taged unions will do that how's the progress with uh Chad vers jippy Tower Defense oh it's it's it's very we're getting very very close I'm going to do more today so anyways you turn thousands of people into Zig fans and I'm looking forward to stack Overflow survey 2025 well let's go Zig async is dead yeah I I'm not sure Zig async is very very interesting I haven't used any async features with Zig I've only just handrolled my own uh thread for input so if we go here I have my own uh I literally have my just my own input engine that runs on its own thread right so I I don't have async uh stuff because I'm not sure I really want async I don't really want async I don't really want to do anything with async I know async A8 is really really useful it's just it's also async A8 is also just really really magical and it's kind of a pain in the ass and when you want two threads that just run independently sometimes it's easier just to use two threads colored functions were a mistake colored functions were a mistake they're very very difficult magical it is magical because there's a runtime you forget how these things work right so in in in in JavaScript it works with something called the event Loop the reason why you have async A8 the event Loop has a series of tasks that are placed into a Q and these and this Q is executed one at a time right and so it pops this thing off and once this thing fully executes it then goes around it does some extra there's like an extra like micro task cue that it can also check and all that blah blah blah blah blah and then once it's done it goes back on and Pops the next task off and so when you make a request right when you do a fetch when you do an await fetch that adds a task this executes something that when it's finished it adds a task to the uh to the event Loop right that's why you don't have to like explicitly await a promise in JavaScript whereas when in Rust you have a runtime you have an Executor that has a thread that is running and this thread is literally checking Futures right it's doing something it's actually running through and and manually checking a bunch of Futures like hey have you ran have you ran have you ran are you ready to run are you ready to run and it's doing that that's why if you block on the executor none of your other threads work right they're all Frozen in time because your executor is all broke right it's not like it's not super it's not super straightforward how this works go works much more like this then this and so go kind of in this Middle Ground which uses a bunch of threads it just uses uh it uses G Funk to spawn these threads and then you choose how to communicate on those threads right go as work stealing Schuler it's a little bit different right it's it's it's it's I I don't quite understand how theer works but it's very very interesting whereas rust is much different different you actually have an Executor that goes through and and does a bunch of stuff green threads someone's asking about green threads there's Hardware threads which are the things that are going to be like your program running in the operating system and then what you can do is you have a thread that schedules that schedules work when you do8 in Rust you got to remember that this relieves that green thread of its work to be passed back to the executor to then determine what next thing should be executed on this on this actual Hardware thread it's like it's it's very very complicated it's it's not straightforward I wouldn't I would not pretend to understand any of this other than from a very very very high level what's going on and JavaScript is a lot easier to understand because it actually only really has one thread right it only has one thread whereas these ones have many threads this has nend threads and I don't know how many end I don't know how big those ends are are you sure that async O8 uses green threads yeah it uses some form of green threads in in in in Rust in Rust it uses some form of green threads right no problem it's just not it's not it's not uh it's just not clear exactly how it works uh asyn A8 and C is a nightmare they're always kind of uh so green threads are Hardware threads no green threads are uh like your programmed inversion of threads you give you have a thread that runs that takes some work and executes that work and then takes more work and executes that work something a lot like this queue you can imagine that you have a queue of work right you have four threads threads one through four or we'll just say one two one through three because it's easier and they're all asking for work off this one this one place you could imagine this exist right and if this thing had a list of items it would do some sort of MW texting right it' have some way to sure that you can't grab the same work twice and then it hands this work to this thread This Thread executes this work while this work get executed on this thread and when it's done it can ask for more work right so that's the effectiveness of it all now how it all works and all that I don't know I've never I've never actually tried to program my own executor my own my own thread runtime so I I I I actually genuinely have no idea how it really works in in practical sense just in a theoretical sense Tokyo does not use green threads either well it it it uses Hardware threads yes but it also has a way to be able to take those Hardware threads and execute tasks on so where does a green thread start and where does a a task stop right like that's the problem it uses a thread pool correct it uses thread pool and pieces of work so it's like what is a what when does it become a green thread versus when is it a uh a just a task like do you see what I'm saying it's like it's a it's a very confusing thing like I said I don't have all the answers to it I just know generally how it works and so it uses a bunch of task tasks and runs them on threads right can I have more work please so it's just like what do you call that thing I don't know what that thing is called implementing a worker queue is a great project by the way I'm sure it's a great one I'm sure it's a great one said jump long jump let's go there you go that's the name of the project um I would say that uh I would like to see Pekka give a much more detailed explanation for this this just sounds like you're not using the type system uh good enough the thing is is that with Zig the type system is opt in rather than rather than forced meaning that you can have a pointer that could be that that could be defined as nothing which means you could get some really bad experiences but you could also say hey this pointer may not exist and I think that's the big thing that I'm seeing right here so if I go to my game objects the most obvious one is this one right here right like I'm saying this pointer does not exist at construction time it is a it is this it is it is potentially a null right now I could probably take this out and make this work a bit better which I probably will but as of right now with how I constructed things I had to do this anyways so there you go all right hey the name the name the name is the primagen
Info
Channel: ThePrimeTime
Views: 7,698
Rating: undefined out of 5
Keywords: programming, software engineer, software engineering, developer, web design, web development, programmer humor
Id: Vxq6Qc-uAmE
Channel Id: undefined
Length: 33min 18sec (1998 seconds)
Published: Wed Jul 17 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.