Hacker News new | past | comments | ask | show | jobs | submit login

> Spawning a process isn't the right tool for ALL X-language communication. But sometimes it is

I'm with you here.

> ...many people do not understand Unix processes and don’t realizing how rare it is to need bindings, ffi, and many libraries

But, this is a much stronger claim.

I can't tell if you're making a meta point or addressing something in the Ruby ecosystem. I mentioned database library bindings because that's far and away the most common usage in the Ruby ecosystem, particularly because of its frequent adoption for web applications.

The author is advocating for not using native code at all if you can avoid it. Keep as much code in Ruby as you can and let the JIT optimize it. But, if you do need bindings, it'd be great if you didn't have to write a native extension. There are a lot of ways to shoot yourself in the foot and they complicate the build pipeline. However, historically, FFI has been much slower than writing a native extension. The point of this post is to explore a way to speed up FFI in the cases where you need it.

It needs to be taken on faith that the author is doing this work because he either has performance sensitive code or needs to work with a library. Spawning a new process in that case is going to be slower than any of the options explored in the post. Writing and distributing a C/C++/Zig/Rust/Go application as part of a Rails app is a big hammer to swing and complicates deployments (a big part of the reason to move away from native extensions). It's possible the author is just complicating things unnecessarily, but he's demonstrated a clear mastery of the technologies involved so I'm willing to give him the benefit of the doubt.

A frequent critique of Ruby is that it's slow. Spawning processes for operations on the hot path isn't going to help that perception. I agree there are cases where shelling out makes sense. E.g., spawning out to use ImageMagick has proven to be a better approach than using bindings when I want to make image thumbnails. But, those are typically handled in asynchronous jobs. I'm all for anything we can do to speed up the hot path and it's remarkable how much performance was easily picked up.






You interpreted my comment as an attack on the author. If they have a special case they want to optimize FFI for this seems like a great way to do it.

> Spawning processes for operations on the hot path isn't going to help that perception.

Yes it will. Because then you do the number crunching in C/Java/Rust etc instead of Ruby. And the OS will do multi-core scheduling for free. This is playing to Ruby’s strength as a high level orchestrator.

I think you’re vastly overestimating the fork/exec overhead on Linux. If your hot path is this hot you better not be calling Ruby functions.

> Writing and distributing a C/C++/Zig/Rust/Go application as part of a Rails app is a big hammer to swing

You’re already doing it. Do you have a database? Nginx? Me cached? Imagemagick? Do you use containers?

Consider the alternative: is the ideal world the one where all software is available as a ruby package?


> You interpreted my comment as an attack on the author. If they have a special case they want to optimize FFI for this seems like a great way to do it.

My mistake. I assumed the conversation was relevant to the post. I hadn't realized the topic had diverged.

> I think you’re vastly overestimating the fork/exec overhead on Linux. If your hot path is this hot you better not be calling Ruby functions.

We're talking about running a Ruby application. Let's use Rails to make it more concrete. That's going to be a lot of Ruby on the hot path. Avoiding that is tantamount to rewriting the application in another language. But, Ruby on the hot path can be fast, particularly when JIT compiled. And that's going to be faster than spawning a new process. The article even demonstrates this showing hot `String#bytesize` is faster than all other options. That's not to say writing a program in C is going to be slower than Ruby, but rather that integrating Ruby and C, which will involve translation of data types, is going to favor being written in Ruby. And, of course, the implementation of `String#bytesize` is in C anyway, but we don't have to deal with the overhead of context switching.

> You’re already doing it. Do you have a database? Nginx? Me cached? Imagemagick? Do you use containers?

All of those things ship as packages and are trivial to install. I don't need to compile anything. Packaging this theoretical application in a container out of band isn't going to help. Now, I need to `docker exec` on my hot path? No, that won't work either. So, instead, I need to add an explicit compilation step to what is otherwise a case of SCPing files to the target machine. I need to add a new task whether in the Dockerfile or in Rake to build an application to shell out to. At least with a native extension packaged as a gem there's a standard mechanism for building C applications.

There's no getting around that this complicates the build. I'm not sure why that's debatable: not having to do all of that is easier than doing it.

> Consider the alternative: is the ideal world the one where all software is available as a ruby package?

I'm not saying we should rewrite everything in the world in Ruby. But, yes, for a Ruby application the ideal world is one in which all code is written in Ruby. It's the simplest option and gives a JIT compiler the most context for making optimization decisions. I'm not interested in using Ruby as a glue language for executing C applications in response to a routed Rails request. At that point I may as well use something other than Ruby and Rails.


> I assumed the conversation was relevant to the post.

Can you not be rude?

You have no interest in the information I am sharing. It appears you already have your mind made up. I have nothing more to say to you.


I’m not trying to be rude. You extracted that one sentence out of a paragraph where I tried to explain why my reply was oriented the way it was. We were evidently talking about two entirely different situations. You removed the context to make it look harsher than it actually is.

But, I agree that this conversation is no longer productive. If my mind seems made up it’s because I’ve done extensive work on three Ruby VMs, two Ruby JIT compilers, and run large Rails applications in production. My assertions on Ruby performance are pretty well-informed. It feels to me like you’re talking past most of points to tell me I’m wrong. Without addressing any of my points at more than a superficial, seemingly flippant, manner it’s hard to have a productive discussion.

Leading off with “I think many people do not understand Unix processes and don’t realizing how rare it is to need bindings, ffi, and many libraries” is a pretty bold claim. It’s of course possible the entire Ruby community is doing things wrong. It’s also possible there are aspects of the problem that haven’t been considered. But, I was hopeful a bold claim would have data to support it.

I care a lot about Ruby performance and if you’ve got novel ideas that can work in practice I’d love to hear them. But, this works best with concrete implementations. If you have benchmarks that show I’m wrong I’ll be happy to concede the entire thread.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: