Hey, welcome back to the Ruby Dev Summit. I'm so excited. I am here with Samuel Williams. Now Samuel lives on the upside down part of the world, you know, where it curves curves under. Uh he's he's from New Zealand and he he's working on some really really interesting projects. Maybe I'll let him tell about it a little bit more, but the projects are a sink and Falcon. And Falcon in particular is interesting because it's like an HTTP server or something that it's like, oh, you're writ in that and
Ruby. That's that's wild. Reminds me of Mongrel with what's his name z right Mongrel anyway, So uh yeah, excited to talk about it. And I think we're going to get a different perspective here because I've either been talking to people who build Ruby engines, right like Opal or you know, I'm trying to get Truffle Ruby or somebody on. But you know, people who work on c Ruby. And then you know, I had Amir Rajon who works on Dragon Ruby, which is a Ruby engine but it's built for video
games, which that was a fun talk, you know. And then I've got people who work out there in the ecosystem building open source. But you know, again it's mostly web like web development, so you know web frameworks are working in Rails, and so yeah, the perspective here is different. I'm gonna stop talking and let Samuel talk. Samuel welcome. I'm just gonna throw the question at you and you can kind of take it from here. But what is what is the future of Ruby? Gosh, that is a
really good question. I think that for me, Ruby is a great environment for expressing yourself as a programmer. Uh huh. A lot of programming languages I feel get bogged down in the detail of the language, and I always felt like with Ruby didn't take There wasn't too much like ped entry in the code. Like it was it was straightforward to write the programs that I wanted
to create. Many years ago, I was working on a property management application written objective C and I started hacking on a web version of this and I started using Rails, and I felt like it was a really great platform, but it was kind of there were some pieces missing for me. HM. When I was working on that particular problem, I was interested in scalability and how you build applications that can handle as of requests. And one area where
I came about this problem was actually a DNS server. And so in my home network, I wanted to make a custom DNS server to back in the had old days with ADSL modems, if you wanted to host a website inside your network and still have the domain name resolved, you would have to have a DNS server that would return the local IPA dress inside your home network for
the webs wow locally. And if you were like on the Internet, you would have to have a DNIS server that would return your ADSL modems ipadriss so you could do port fording like poor ad or whatever, right, And so I was trying to build this website, like, well, this is kind of an interesting problem, and so I kind of switchedcars a little bit, and I wanted to build a DNS server that could do this for me. And I thought this, you know, Ruby seems like a reasonable language.
Is it's basically just pan matching on the host name and then returning a different DNS How hard could it be? And so I created a probably one of my first gyms. It was called Ruby DNS and it was a a DNIS server for Ruby. And the first time I ran this my whole network like crash. Yeah, running single three to DNS service isn't you know, very
practical. Essentially, every computer in your network is doing DNS queries like multiple queries second, and if your DNS server can't handle the incoming load will stop working, like your web browser will stop working time, you know, into stop everything, just like cries to a whole So I started, you know, it was my first real experience of concurrency and scalability problems because it's just like, well, this is an easy problem, like, you know,
it's a well defined problem. You know, message comes in, do some kind of computation, you respond, you know, it's really straightforward. And I felt like really didn't provide the right tools to solve it, and that that to me was a little disappointing because it's like, well, the code itself is clear. You know, I can write down what I want, which is I want to pay and match this host name and return this IP
address if ther comes from inside the network. Otherwise like pass the request down you know, to the to the I s p's so so so to me, like it was a straightforward problem. But the way that Ruby, the tools that Ruby provided to solve that problem, weren't weren't necessarily convenient or scalable, or it wasn't even maybe obvious even if Ruby at the time could do that, like how you would go about doing it. So in that first instance, I started trying to work on the multi thread of DNIS server,
and that was difficult because it's still has scalability issues. And I started learning about like new texts and and parallelism and all these like sort of challenges associated with using threads, and that those challenges they weren't insurmountable. But I felt like, now my code is much less clear. I'm writing this code, I have to deal with these concerns around concurrency that in PARALYSM they didn't really
want to. I just want to say, basically like here's a request block of code that handles the request, and here's the response, and then we'll
deal with anything else. So at this time specifically, I started working on an interesting test case for this, which was called Wikipedia DNS, which is a DNS server which it basically doesn't HGP request to Wikipedia to get the summary for a topic, and so you can get Wikipedia summaries through DNS, and so what was interesting that this problem was that I had to do an HTPP request and so as you can imagine, doing hp request is kind of slow,
and so it was an interesting test case for me because I was like, how do you make a DNS server that's doing this more efficient and scale better? This problem is the same problem as you see applications and in other types of response systems. And so at that time, Tony Tony rc Area, I think it's how he pronounce his last name. He was working on
celluloid and he was working on actor based concurrency. So active based concurrencies where you define essentially a unit of work and that unit of work happens independently of other units of work, and it uses the actor model, which is message
passing. So you have these different light systems. You have like a every connection that comes in could be its own actor, and then when it needs to do an HTV request, goes and talks to another actor, and the actor itself is then responsible for doing the ht requests, and once that request is furnished, it comes back to the original beas is, Hey, you can keep on going. Yeah, And then a lot of those systems,
those actors are separate processes. They can be or separate threads, and so at that time I was like, well, this is seems like a neat idea, Like maybe this is the right approach, And so I started working down, you know, going down that pathway and building that and so I built celluloid. Danis and I worked on the cellulord gym quite a bit.
But the biggest disappointment there, I think was the fact that celluloid was so complex that it kind of collapsed under its own Weightman complexity was just to agree. And I think the actor model, when you start trying to build a practical actor model, does get extremely complex, like supervisors linking actors together. One particular piece of code that really bothered me was this concept of linking actors together. And so the linked actors, where one actor crashes, the other
will get informed of late restarts. Kind of forms a supervisor relationship. So if you have like say a web server, and that web server blows up, you have another actor whose sole purpose it is to restart that server for example. Right, this is this is how a lot of the ear laying and elixir stuff works. That's correct, Yeah, yeah, And I'm not really like criticizing earl and elixir I think they're great systems for the problems they
solved. But for me personally in Ruby with Sally Lloyd, the piece of code that bothered me the most was this one piece of code which basically has like a five second time out where it basically tries to talk to another actor and if it doesn't respond in five seconds, it just blows up basically, And I was just like, why is it five seconds? Like and the
whole, the whole like semantic building like building block above. It was all based on this kind of like implementation detail that really bothered me, and it the challenge there is there were too many choices to be made and the semantic complexity just got out of control. And so as a consequence, Sally Lloyd never really reached a one point over release. There was never a point where we could say, hey, this is what Sallyloyd is and and this is
the foundation of what you can build other things. So I basically built like a version of Ruby DNIS that worked on Stellulod. All the way to the end point I was just like this is I just can't I don't want to release this, and so at that point I made the decision to release to work on, like to do this myself. I kind of got sick of depending on other people's ideas, was like, and I kind of know what
I want to do this right. And that was the birth of ASIN, the gym that I created for doing Ruby's concurrency concurrency within Rubius, and so asink was was born out of frustration. I suppose you could call it frustration development. That's frustration development. You know, there are a lot of very
great things that came out of frustration driven development. Absolutely, and I knew like for me, like one of the key goals was having a specific, a well specified interface and having that well specified interface as quickly as possible, and and and not not trying to and not let the scope of the problem and Samandis create beyond what was manageable, because ultimately, when you start doing that, it's the it's actually the engineers who pay the price of complexity.
As a as a person who is trying to solve and build a foundation for the engineers, every decision you make is at least I personally think, if this is not complexity, I can solve and hide from the user. Am I am I comfortable with exposing that complexity to the interface that the engine is ultimately you have to build the applications on, because when you start doing that, then instead of you paying the price, you're basically just passing it on
and saying, hey, I can't solve this problem. Yere you deal with it and then what you deal with Instead of you solving that complexity in one place, you're basically forcing every engineer who interacts with your interface to solve their
complexity. And they spoke buggy an incomplete way, right, So I think it was really important to me to say, hey, look, this is the interface I'm going to have, you know, and for me, there was a task based interface where tasks run concurrently, a well defined way of starting them, a well defined life cycle, and essentially being able to say, hey, this is this is the whole interface. The implementation will probably get better, but this is the interface. This is the fundamental foundation which
I think concurrency should work. And so there was a stable flag built that and released it I think in like three months, Like I can't miss you remember the exec details, but I think we got to a one point of release of facing pretty quick and that was that's you know, that was you know, the rest is history I suppose so, so yeah, So the question was what is the future Ruby? Do you think concurrency is the future
Ruby? Then this kind of concurrency. So look, I suppose my mental model has always been Ruby is is a language and instead of tooling and frameworks that as well utilized across the work ecosystem, like lots there's lots of big
companies using Ruby, right. And one of the things I've talked about often in my in my presentations in conference talks is I try and give like a few minutes on climate change and talk about the nature of it and technology and how we're I don't plan to be an expert on this topic, but like being a parent, is kind of concerning like what's happening right now. And I think technology, I think that I have to say I'm probably like a
technologist in terms of like what solutions we're looking towards. I think it's just because that's who I am, right, and it's Ruby as being a technology which is widely adopted, but that the models and technologies that we use with then Ruby to achieve scalability are less efficient than they than they could be. Ok. And so I think that my goal has always been to provide more efficient primitives to build web applications with Ruby, and in particular to retrofit existing
applications with minimal changes to take advantage of that increase concurrency and scalability. So give you like a really practical example of this. We had one of my friends had an application that was running on like, I don't know, up to eight instances of Perma and it still had like ladies issues when there was a spike and load and it wasn't it was mostly ir that they were doing. And they migrated to Falcon and they got it down to like one instance
and I think one more instance for worse or something like that. Oh wow, So like this the kind of like success story in a way, I suppose, because for me, you know, someone could take an existing application with minimal changes, run on Falcon and then reduce their carbon footprint of the application. I suppose you could call it so like the future of Ruby in my mind, Like for me personally, you know, apart from all the great work that people are doing, because there's a lot of it is more
about how do we take all that. That's what I'm looking for velocity. You know, all of this lines of source code and make them more efficient and work efficient. And so I think for me, the future of Ruby is all about efficiency and doing more with less and that's pretty much what underpins
the async model. You know, we can do more IO with less CPU cause basically, well it's it's funny too because you know you're talking about this in terms of like climate change, and you know how well we're using the resources we have. But the reality is is that it's actually if you can run it on less cores, maybe with less memory, it's cheaper anyway, right, It's a way saves money. Yeah, absolutely, Like then, since I gave before the example I gave before, it was saving money.
So yeah, I think that there is Look, everyone has their own use cases and in their applications. Sometimes the CPU be sometimes that I hev. It really depends, But I wouldn't want to say my experience with real replications across large companies as extensive. I've worked with a handful of them, and I get to see people with the internals of people's applications and look at tracing and and APMs and whatnot, and they looked at the data. There's only
so much you can achieve in one lifetime. But from my experience, a lot of applications are iobou they are. You know, anytime you have a web request, you know the h GDP or something like that, you potentially significantly I abound. And I suppose there's lots of strategies to deal with that. Sometimes people use background jobs, sometimes they will use background threads. There's all sorts of strategies you can use to deal with improving the efficiency and performance
of this type of code. But I think, like a lot of it, a lot of the time you have the trade off of code complexity versus efficiency. And there was a talk that really inspired me initially, h I don't the talk really inspired me. I think the conclusion of the talk, like many years later, was ultimately not as good as I hoped it would be. But there's a talk C plus plus courroutines and negative overhead abstraction which
really inspired me when I was looking at curroutines and fibers. This talk basically starts right from the beginning and looks at how traditional punch card computers work and how you have like a stack of punch cards and you basically step by stick to build like a compiler. You take your punch cards, and they go from one machine to the next, and they go to the next machine,
and you're taking these whole stacks of cards. And they were basically saying, well, how do we like that If every step takes ten seconds, then the total processing time there's going to be like ten seconds times a number of steps. So how do we make this faster? And their their solution was to when one punch card is finished from one machine, you put it to
the next machine. Basically, so instead of every step taking ten seconds, you can kind of combine them all together because the punch card is flowing to end. And but traditional programs don't work there, like a function call. When you make a function call basically saying hey, here is a bunch of inputs and then give me give me some result hm. And there's there's no easy you know, if you if you feed in ten gigabytes of data, it's going to churn away on that data and then come back and say here's
your team gigabytes or whatever. And so this is kind of the same problem as the punch cards. You know, if you have a whole bunch of functions you want to chain together, then the total lazy of the system is all the individual steps added together, right, and you can't really avoid that. So the whole idea of a co routine is to kind of short circuit there so that when one function is finished with one data point, that can
just pass it onto the next function. And so this instead of being like running and they're very manular level, they're running kind of almost and lockstep on one data point at a time to hold through the whole pipeline. So this talk that I watched about C plus plus curatoons and negative overhead abstraction really inspired
me because I never thought about negative negative overhead abstraction. You know what I mean about this is when you look at languages like jazzascript for like pulling this one out, but you see things like a single waight the keywords, and everyone is like, wow, you know now we can do like a single weight, And I'm just like, so you have to add these keywords everywhere and like we write all the code and yeah, I'm like, this is really problem. I want to spend my time doing, you know, like
I want to go through my whole code base and rewrite everything. You know, imagine if if multi process or multiple threads were like that kind of cooperative concurrency with explicit keywords for yielding. At every point that you thought yielding would makes sense, it would be another year. And you see this in the very practical terms. You see like JavaScript libraries which have both synchronous and asynchronous interfaces for the same Yeah, and a really common example of where I think
this is a huge problem is logging. Now, and probably there's other ways of solving this at the core of JavaScript, but if you have a log function and the log function is doing some kind of ir I you always get to go through the entire source curtain and change your log function from like a synchronous log function to an asynchronous one, just because like maybe the back end change from standard through like an HQP to an APM or something. I don't
like. It has always struck me as odd that people would want to go through and retarget them and rebuilt interfaces and make concurrency and explicit part of the interface when actually it's much more convenient when it's implicit. I do give these arguments for both sides there, but for me, I'm lying firmly on the implicit side. Right. So I suppose with JavaScript being so explicit, has
some advantages, but it also has some big disadvantages. And so with with curroutines, I felt it's a great model because at less you hide a lot of the scheduling, and so with acing, I was like, okay, i' many of use fibers to do this to try and hide the scheduling, and it's a kind of green thread model. So with acink one point zero,
I wanted to show the proof of concept. I wanted to show I want to give interface correct, but I also wanted to show like this was feasible, and so acin one used a lot of rappers internally to do IO and make sure that I was not blocking and it didn't necessarily pick up every single operation. There were a couple of like outstanding ones like waiting on a process to exit or DNS resolution would be like another one that that acink one
pointer didn't handle concurrently. So after I felt like ACNC like it seemed successful, like I could build like a web server and I could run applications on and it basically just worked as I hoped it would. So I went to Matt's at Ruby World conference I think in twenty nineteen or sometimes around there, and I said to Matt's, Look, we've got a perfectly like I've built this proof of concept, like it works. It gives you insane scalability.
And I think I demonstrated the Ruby comf Taiwan and a talk called the Journey to one Million where we did one million simultaneous web sockets and a single Ruby process, which oh wow, yeah, it's a fun demo. Yeah sorry, go ahead, No, I'm just saying that that's amazing. Yeah, Matt, Matt's pressed the button on the keyboard to do the final connection. So it was great, and I think, uh that that whole experience. I started looking at the performance because you know, now we've got the proof
of concept, we've kind of proven the interface. What's the next step, So I said, to Matt's, we need to make it possible to hook into Ruby's internal schedule operations so that we can redirect those operations to the some kind of scheduler that can then manage the fibers and have some kind of event.
Look, so a schedulist job in Ruby is to basically take an operation like a web request, and if that request is going to take some time to completely, say one hundred milliseconds, maybe you're talking to an external API and it's it's slow. Then the schedulists job is to say, hey, I'm going to pause the code executing right now until the operation can continue.
And then when the operation can continue, we will resume execution. And so you have all these like little chunks like in a RAG application or a DNS server for that matter. You basically have like a request coming, you're going to do some like IR operations, and you're going to run and you have a whole bunch of these operating all concurrently. So the schedulest job is to basically say, well, I'm doing this request and I can't go any further
right now, so I'll go and do one at some other requests. I can't go anyether, and I'm going to do some other requests. Now their responses come back from their website, so I can keep on going, like Wikipedia DNIS for example, where it was doing an API called a Wikipedia to get the summary. So now I've got the summary, I can and procese it and see the response. So the schedulest job is to do all that
work. And so what we do is you talk about this and this sounds like how my friends who switched from Ruby to no JS explained why no JS was better. Well, we have it all in Ruby now, so yeah, we have it all in Ruby. I tried to explain that to people. But anyway, so I think one point I was the proof of concept. I talked to me and I said, look, MAT's we need the hooks and Ruby so that we can redo it these operations to a scheduler and
efficiently scheduled that. And so that's what we did. And it took a took a couple of releases of Ruby to kind of iron out all the tanks. So we had pretty normal. Yeah, it's normal. In fact, it's I wrote a book a blog post that two years ago, like for the release of Ruby three point one or something. I never I never published the blog post because as I was writing the blog post, I found a
bug. It was like, oh, no, I have to wait a whole year to like fix this bag before I can like never came back to it. But so we implement the scheduler hooks. So Ruby now has something called the fiber scheduler, and the fiber scheduler is providing a whole bunch of hooks, a couple of like io weight for dealing with like reads and rights
that are blocking. Address resolve, which deals with danais so I concurrent danis resolution process weight, which deals of waiting on a child process to Except there are a bunch of specific ones like io read and io right, and I'll
talk a little bit about them in the moment. And so there's all these hooks, and so the Ruby interpreter, when it's running code that the user wrote, if that code executes an operation that would block it gets redirected to the fiber schedule, and the fiber scheduler will then manage the concurrency of of
multiple tasks so they can be executed most efficiently. The benchmark I have for that is actually like going into this whole problem even with Ruby DNS, was like, how do we run the most lines of Ruby code as efficiently as possible? Is the fiber schedule is conduct switching between between fibers and tasks and basically trying to execute lines as quickly as possible. I suppose you can look
at it that way. So I think two point zero was the first release of ACNC that took advantage full advantage of the fiber scheduler, and it was really like a major milestone. I suppose Ruby, even if it's not publicly obvious, why you can take an existing roomy program run it on top of acinc and gain significant advantages to I concurrency and like pinch, like other forms
of concurrency like DNIS resolution, waiting on child process and whatnot. And so it's all well and good heaving this foundation, I suppose, But maybe that leads us to the big topic like Falcon and how that works and why that's important. So as we know, like Ruby, it's a great environment for an age applications for for lots of reasons, Rails probably being like the biggest one. Yeah, I felt like my Denis server wasn't was was one like
for me it was my proof of concept. But then I was like, well surely we can write a web server, like can it be famous? Right? Yeah, exactly totally. So basically I built Falcon as a proof of concept to see, like, you know how good it is it you know what kind of performance can we get? And so Falcon was was born out of that kind of curiosity, I suppose. Obviously we wanted to use rag Rack is the standard interface for between web servers and replications in the Ruby
world. Yeah, and if you optimize for RACK, you optimize not just for rails but for Sinatra and Rhoda and all the others because it is that core piece the HTTP interface to Ruby. That's right. Yeah, And so it's like a volcane of worms, like oh, rack two point zero. When I when I started building building Falcon, I was like, I want
to how RACK works. And I've done I built my own framework for Reck in the past, but it was really just like, as a consumer of the interface, I wasn't really considering what it's like to be on the other side of right equation, on the service side. So when I went to the RACK issue tracker, like it was many years ago now, there were like hundreds of open issues. No one was really maintaining RACK, and I was like, wow, this is a little said, this really critical piece
of infrastructure. It's kind of I suppose it's a little hidden from view because most people wouldn't really need to know why RE exists or why it's important. But right, so RACK is essentially a CGI gateway between It's basically using the CGI specification as an interface applications, and so every web server that talks to a RACK application with a request and then gets a response from their application.
Is essentially using the guts of of the CGI specification, like so as path info is one of the more common like CGI fields, and it's it's defined either c g I or it's used by RANK. So I was really interested. I was really interested in HB two at the time. It's like, there weren't many good implementations of HP two for Ruby, and so I went and created one. There's a gym called an h pop does h P one, HP two and hopefully H three, and and I thought, well,
why can't we support HP two directly from web service? It's pretty it's a pretty good protocol in lots of regards, like it's a bit of a HP one is text based, line based. H B two is using binary framing, and so it's it's harder to stuff up HUP two, so it's a bit more secure, and it has other advantages as well. So it's like, what, you know, why can't I run a RAC application HB two. Well, as it turns out there's e g I specification that that RACK
was sort of implementing. Well, semantically, you can always write proxies between HP one HB two and HP. They've tried to have the same semandix between all the different versions. It's just the protocol itself on the why that differs. But but Rack itself didn't really expose a good model for that, in my opinion, and so I started working on that problem. And so one of the biggest most important changes that I feel like I made to Rank was
the ability to stream requests and responses. So this means that there was a I had a conversation with the engineer many years ago and they were like, we're generating CSV, like a lot of CSV from a RAILS air and it gets buffered the whole lot, and it's like multi ugabytes, and we're killing servers because because they came the whole response. How do we start streaming this? And it's interesting that that's even a complicated question to answer, in my
opinion, because I don't think it should be. And so Falcon and Rack the changes that I made, I was sort of trying to change to make it easier to stream responses. And another piece of this is like web citeits even today, rails still uses a hijack mechanism, which is where it basically the request comes in and rails basically steals the whole connection and plucks it in its own event loop, separate to the server itself, and then starts talking
to the website protocol on that. But the biggest issue with that is, like, because it's hijacking the whole connection, it doesn't work with HDB two, which supports multiplexing on a single connection, because with HB one you have one connection per request response, and it's okay to take that whole connection and hijack that. With HB two you have lots of individual connections running on one TCP connection. So I worked on RACK and I solved this problem. We
released RAP three three, three point whatever. There was quite a lot of shown as we figured out a few compatibility details, and so now it's possible to run web socits natively on a rat compatible server that includes perma Falcon. I think even webrook is supported with you know, you can just run a web soce straight on the request. Yeah. Yeah. And so I was really pleased about this because it's sort of kind of bait to the question,
which what is the future of Ruby. Actually, I suppose as an engineer, I was really disappointed at how badly web socits were handled in Ruby. It was like websites were vented? How many years ago? And how long has it taken us to get to the point where applications can just like native And then I think that I don't want to be too critical, but I think that's how Ruby back in some regards. You will look at that and go, well, Ruby can't do this, and it's like, well,
yeah, and how we're going to solve that problem? And so I think the future of Ruby in some regards there is catching up to do the technology side, but I hope that things like Falcon and as provide the right foundation
for building those applications and going forward with improved concurrency and scalability. Right, cool, Well we've spent It's so funny because I usually have to prompt people as I interview them, and you know, to clarify more things and you know, and then it's like, oh, we went for you know, however long and yeah, I mean I feel like I maybe added some color
commentary, but for the most part. It was really fascinating though, to have you kind of walked through that whole process, because yeah, I mean, concurrency is one of the things that I hear a lot of people talk about and it's some of it is down to, yeah, am I making efficient use of the hardware? And do I get the performance gains out of right? It has four cores? So why am I not using four cores? But the other end of it is is that and we all want that
kind of efficiency. But but the other side of it is is, yeah, you know there's some capabilities that come along with it that that, right, it changes Actually it's not just about making things more efficient. It actually changes applications, right, And so just looking at that, it's it's very interesting to look at Okay, you know now that I've got these things working for me, Yeah, I've got I've got these options, and so that
that's very very exciting. I'm wondering too, because some people have left Ruby because of the concurrency or other concerns. Do you think we'll pull some of those back or do you think they're just going to stay in whatever land they went to to find that? Gosh, that's a good question. Look, I don't presume to know what people do or don't want as engineers. I've always just felt like I want to scratch my own note. Right, Look,
I suppose yeah, the biggest elephant in the room. There will be something like Alixa and yeah, look it's a great technology, and crystals as well. From my point of view, just look at as the biggest thing for the buck, Like if I went to work on Crystal or Elixir and
solve or improve their concurrency. It's sort of like if at times like the size of the market or impact, And so for me, like the size of the impact for Ruby is just so much bigger, right, So it's even the same amount of effort because it's multiplied by the size of the market, has so much more total impact, right, And so for me personally, that's the equation I work from. I'm like Ruby is a low hanging for it is such a great scope for making existing applications work better and more
efficiently. And that's what I personally find exciting and seeing the early adopters take Falcon, use Falcon, you know, use acing HP and derive those in credible benefits and build and and and and Finitially, that the the nature of the kind of application that can build the web sockets and service and against and all those other kinds of technologies that are now very easy to use. We've we've lowered the bar and like on accessing that level of interactivity and so it's
exciting to see what people do with that. So to answer your question, like I suppose it doesn't really matter because people will use the technology of the most comfortable with and that's okay. Yeah, And like I suppose at least if someone's arguing that Ruby's not capable of doing like concurrency, we now have a counterpoint, which is, hey, actually it can, and it's really
good and it works really well. And the only the only argument I would really say that that works against that is like it's still early days, but like I don't expect someone like this to be adopted overnight. Like it's already been six years and we've got our early adopters, which is amazing, but it takes time for companies to Companies are extremely slow on adopting new technologies, and so we're going to be I said, look, I know these major
companies using anything. I can't really talk to them, but you know, it's hittening and I think that that's a good you know, make it as good as we can for the engineers. If it solves an engineering problem, they will do like people will use them, and I think that's yep, absolutely well. And it's interesting too because as I've done these interviews and it kind of goes back to the point you were making earlier, and the point
that several others have made is that Ruby, it is so expressive. It just gives you so much in the way of how do I put it, So people are adopting things like Python. Python seems to be, you know, having a renaissance these days because it has powerful math and science libraries that and it's approachable enough so that people in academia can go and they can do
their thing with it. Right. So that's It's not the expressiveness of the language, right, It's not you know, any of the things that in my opinion draw me to Ruby, right, And so as long as it's fast enough, it has enough of the right either libraries or capabilities to solve my problems and things like that, right, I'm happy to use Ruby. And the thing that draws me in is the way that the language is put
together. And then if you expand that into things like Rails or a lot of the other libraries, really what you find is you find that it's those have adopted the same expressible approach as Ruby. Right. So when I was learning rails, I learned rails and then I learned Ruby to learn rails, right, and I learned Ruby through rails. But you know, it was all very intuitive, and you know, kind of it got out of the way of me having to really deeply know the technology, and I could really
think about the problem space I was in. And so yeah, to the extent that, hey, it gets better and better and better and better. That that's the thing that excites me, right, is that it's already good enough. But to see some of these advances, that that's exciting. And yeah, like you said, we've got some early adopters. We've got people out there, you know, trying out Falcon and acinc and things like that. And what I found is that these things is they tend to make a
difference for more and more people. Then then the word spreads, and then what happens is now the state of the art is not Puma, it's or maybe Puma adopts some of the things from Falcon and it is Puma, but it's a Puma that's way better, or it's Falcon, or it's Yeah. I have a close working relationship with Nate and a couple of others and which are cross cliberate all the time. One. Oh yeah, well I also because if you do something brilliant, right and I'm using Puma, I still
want it. Yeah, yeah, absolutely, Well you can use acink inside Perma. It works fine, Yeah, you just if you have So this is just a fun aside. I suppose Puma is using a thread for each request. There's no reason why you can't put like a block, an ACNC
block in their thread and then multiplex out multiple work requests. So let's say you're we're working on a service as to talk to like say, maybe you're doing like a you know, identity checking system or something you need to talk to like three different remote systems to validate someone's bank details, address or something else, and you want to talk do that as quickly as possible, even inside Perma. Well, I guess you have two options. You can use
ah is it called ethon, There's like a there's something called Hydra. There's a gem which works on top of lib curl. I think unless you do like comparency multiple requests simultaneously, or you can just drop in an ACNC block and just do you is XGP and it will work as well or it's not probably better and so like you can't embed as and consider perm and derived significant benefit if you know, if you have explicit ioconcurrency that you want to solve
for. So, yeah, it's pretty neck like it's it's it is very composable in networkun cool. I'll check that out too, all right, Well, are there any other things coming in the Ruby or the Ruby community eco system core length you're jazzed about. Yeah. One of the thingsures I've been working on in Ruby tangentially is io buffer, which is an alternative to using
strings for network io. Okay, it's currently markets experimental, it's been in like the last two or three releases of Ruby, and it's used by the fiber scheduler too. Have an efficient zero copy mechanism for basically saying we have a string and we want to read into a part of that string, like someone's trying to read data from the network into the string. We don't want
to like just read data and then copy it in there. And so io buffer can be a slice of that string and we can efficiently pass that into the Rubies fiber scheduler and then the five responsible for reading into that piece the buffer. The surprisingly, I've had bug reports from like lots of people in a bad way, like people trying to do stuff and finding inconsistencies or all things together. And I was surprised because I didn't think people would be using
it as much, even as marked as experiments. But this is one of my goals that things get better, So that's fine, Yeah, exactly right. One of my goals is to try and tam zero copy networking, and Ruby Ruby right now does because of the way strings are designed can be each
cases for networking, IO can be quite complex to avoid copying data. Copying data isn't exactly the worst thing you can do, but CPUs only have a bandwidth of like between fifteen hundred gigabytes per second of memory bandwidth, and so like the less of that you consume just copying data because you do it, the better. And there's another I said earlier. I had mentioned something specifically about the IO reading. I wrote five schedule looks andy bit, it's a
good opportunity to touch that. So then Ruby, there are operations like reading and writing from a socket or a file or something, and you want that to be a concurrent and it turns out that some of those operations are quite hard to do it concurrently, like reading from a file concurrently, there's no good API for that and general Unix, if you try to say is the file readable, it will always say yeah, it's readable, and it's unlike I, say a network socket, which if the data hasn't come into the
network card, then the socket is not readable. But a file is always available to read, and so there's no good mechanism for basically detecting their case. And so you get APIs like what's called AIO, which lets your schedule operation be say I would like you to read the data from this file and then tell me when it's done. But these APIs have always been slightly plunky
to use, and often that don't work as effectively as you'd like. So there's a great new API called iouring and ieuring actually is an asynchronous system called for Linux. So there's a whole bunch of light system calls that by default synchronous, like the operating system will take some time to do the operation, and there was no easy way to do their operation in a non walking fashion. There was no API. There's no way to say, can you start
doing this? And then tell me when it's done. There was no easy way to do that at the system call level, and so what the ie you ring is is it's it's a buffer, a submission buffer and a completion buffer. And what you do is when you want to do like a system calls specific system call, you basically write all the details of that system call into the submission buffer and then the operating system will basically just read along that
submission buffer, taking out the operations and then doing them. And when the operation is completed, it will put the result of the operation into the completion buffer. And so you have instead of having synchronous system calls, you now have asynchronous system calls right And as time goes on, more and more operations
are being added to URINE. So it's really exciting because it allows us to do things like one of the ones, like a simple example of where there was no asynchronous version if allocate, which basically allocates a file on disc and this can take time and it's a blocking operation potentially. So if you want to create like a thirty gigabyte file on disc, use if allocate to allocate the spacefully start writing to it, otherwise you might get halfway through and you
can't writing more data out of mimerica or something. Now with I you ring, you can schedule this operation into the ur ring and then you can wait for it to complete in the background. And so this is really fantastic for
the fiber scheduler because the fiber scheduler can take more and more operations. And in this particular case, I read and I writ are examples of those operations where you can may see, hey, read from this file and when the operation is complete, tell me that it's done right to the operating system instead of trying to manage it itself exactly. And so I'm really excited by this
functionality and it works as off to day life. You use the last version of acink, you get I support and links where it's where it's supported. And again, like it's it's a complex system. There will be issues to work out, but we are solving those problems and we're seeing significant advantages in production with these types of interfaces. So I think, yeahs original question like
what is the future of Ruby, I think there's two pieces. There's the catcher, which whereas like things like web sockets should have been better at earlier on and I think basink solves part of those problems, and then there's just adoption of like user adoption, but then there's also exciting things like have Ruby actually interfaces with the operating system to do things more efficiently, and the low level interfaces and hooks and just like design required to do that, and hopefully
like most of that's hidden from the end user, so you just install a new version of Ruby and things work better. And so for me personally, that's what I'm focused on and where I think I want to spend more of my time. Very cool. Well, we're over the forty five minutes that we have scheduled, and I have a whole bunch here at tew on. Plus we're also scheduled to do a Ruby Rogues episode coming up soon, so you know, we can go into more detail there. But this has been
really fascinating. Thanks for coming and talking through this. It's a little bit different angle on the future Ruby than kind of what I've gotten from other folks, and so hopefully some people dive in and go, oh, well, maybe I can help with that, or oh I'd really like to understand that more if they do want to reach out to you on that stuff. How do they find you online? The best way to do it is get have
discussions. So I'm good, I'm good. Any of the projects you're interested in, just find the discussions and if it's not enabled, just pring me on, bring me on the other discussions. Most of the major projects have discussions enabled, and it's a great place because there's a bunch of people who get involved and have experienced using it and can help some questions. Yeah, okay, sounds good. Well we'll go ahead and wrap up here. Thank
you so much time folks the opportunity to talk as well. Oh thanks for coming. This is like I said, this has been really really fascinating and yeah, until next time, folks. Max out
