Comment on What software stack would you have chosen for Lemmy?

<- View Parent
Dark_Arc@social.packetloss.gg ⁨1⁩ ⁨year⁩ ago

Well, it seems to work well enough for Mastodon. I’d also point out that there are websites far larger than Lemmy using Rails at scale (Shopify and GitHub being the primary examples). It scales quite well.

I could be mistaken, but I believe these sites are normally “using rails” (as in they shell out to other languages, Go has become common, for performance critical end points or portions of those end points that need to work a bit harder). I also suspect they’ve got some pretty heavy modifications.

Without benchmarks, this is a subjective statement. Ruby 3 is quite speedy now, at least I find it to be. Performance is even better with YJIT enabled in Ruby 3.2. I think this “Ruby is slow!” stereotype is left over from before Ruby 1.9 when YARV was introduced. Is it as fast as a native language? No and it never will be, nor will any other interpreted language. But this idea that Ruby is somehow the slowest possible interpreted language has not been true for a very long time now.

I haven’t worked with Ruby since… 2.5(?). That’s very fair about the JIT improvements.

I’m not entirely sure what you mean by this, but Ruby introduced fibers a while ago.

The Ruby language itself has fibers, but last I knew Rails was not making use of fibers for ActiveRecord. The problem is effectively you’re in an interpreted language (bad enough) without real parallelism (worse). So, when any IO occurs one of your non-parallel threads is blocked. Ruby jumps around to process the different threads, but this creates a context switching problem and you lose a lot of performance to the preemptive multitasking’s context switches (and resources are hard locked up by the IO).

With a coroutines or fibers based approach (cooperative multitasking) you don’t need multiple threads, the “callbacks” just fire into the appropriate place when IO is fulfilled (what NodeJS is famous for). You can get way better throughput and it becomes trivial to execute queries that aren’t co-dependent in parallel (so your page that depends on 10 different queries gets resolved much faster, and your app can work on other pages while that data is being resolved in the background).

It’s not a silver bullet, you can run into issues if you have CPU bound tasks on the event loop thread (and thus create latency issues as things just aren’t getting finished). However, in a well designed web app that shouldn’t happen anyways (this stuff should be in background job queues, or at the very least running in separate threads – in Ruby that likely means processes unless the threading has significantly improved).

Not true anymore. Ruby has had a compacting GC for a while now. This was a difficult problem to solve because of Ruby’s support for native extensions. Otherwise it would have been done much sooner.

That’s good to hear.

You can use RBS (built into Ruby) or Sorbet (third-party Shopify project) for this if you want. Or don’t, I personally prefer Ruby’s duck typing. I don’t think a language using someone’s preferred type system makes it “terrible” just because it’s not what someone likes. Other people are perfectly happy with it.

RBS is definitely newer (I stopped working with Ruby around 2018). Looks like Sobet was just getting started. Also good to hear.

I’ve changed my stance over the years from “it’s a matter of preference” to “it’s objectively bad.” The lack of any type structure leads to a significantly larger requirement in unit testing. Unit testing can be good, don’t get me wrong, but in our org it had gotten to the point we were writing unit tests that effectively tested “did the code change” … and I don’t think that’s a good workflow. You’re lacking a compiler to do type checks for you (when you refactor something) so you have to write all the code to catch things the type system would’ve taken care of for you.

Put another way, I don’t consider a unit test for a function as trivial as:

return a.y + 1

To be superior to the type system telling me y no longer exists. However, if y no longer exist, I still want to know before a customer bumps into the inevitable crash.

Ruby being a one-stop-shop for Rails has been a criticism of it for years. I’m not sure how that’s a knock against Rails or Ruby though. I personally write all sorts of non-Rails things with Ruby as I love the syntax and greatly enjoy writing Ruby code over that of, say, Python. To each their own though. There’s Sinatra, Jekyll, Fluentd, Chef, etc. all written in Ruby.

The problem you run into here is a lack of mature libraries to leverage if you want to do anything non-trivial. e.g., our application needed to read from spreadsheets. The Ruby libraries either A) didn’t have support for common formats like xls or B) would load the entire spread sheet into memory represented as Ruby objects (you can predict how well that performed :) ).

Without potentially breaking a NDA, that made the effort to get efficient spread sheet processing much more challenging than it would’ve been if we’d picked a language with more reach; this is just the main example I think of, there were others.

Drop in gem that will automatically solve 99% of N+1 issues: github.com/clio/jit_preloader

I think we eventually started using something akin to that. However, I’m a big advocate for making the wrong thing look wrong/complicated, and Rails very often makes the wrong thing look simple. Note that gems like this don’t really solve the problem they just inform you when you’ve made the mistake, or alternatively forcing your app into hammering your database even in situations when it doesn’t need to (which can drive you back to my earlier points about the lack of cooperative mulitasking to deal with the IO bottlenecks).

Granted, we operate on the idea that any good engineer can get up to speed with a framework in a reasonable amount of time. I don’t believe in the “you are only worth the frameworks that you know” idea.

I agree, but there is something to be said for hiring people that are extremely knowledgeable in the framework to help highlight solutions (like those you’ve mentioned here) vs “you’re a great C++ dev, now go do Ruby!” It’s not a deal breaker, but when you hire folks like that the time to get them up to speed is going to be far higher, and they’re going to make mistakes that in a sense “aren’t at their experience level” (particularly with the former point about making the wrong thing look wrong considered).

But I wouldn’t go so far as to call any of them “terrible.” Maybe it’s not my/your cup of tea and that’s okay.

I’ll concede my initial reply/stance was a bit bold, and you’ve definitely highlighted serious improvements in the ecosystem I’ve either overlooked or forgotten about… Perhaps I should’ve said was terrible; I’m not rooting for Ruby to fail, but I did have a bad experience.

source
Sort:hotnewtop