top | item 45856142

(no title)

brunosutic | 3 months ago

The usual response to this complaint in the Ruby/Rails community is that optimizing for nanoseconds, or even milliseconds doesn't matter when the same operation also involves multiple database queries or API calls.

Let's take this example from the article:

  Billing::Plan.find_or_create_all_by_attrs!(
    1.month => {standard: 10, pro: 50, enterprise: 100},
    1.year => {standard: 100, pro: 500, enterprise: 1000}
  )
This ensures six billing plans are created. That means 6 DB queries and 6 Stripe API queries, at a minimum.

discuss

order

dlisboa|3 months ago

> The usual response to this complaint in the Ruby/Rails community is that optimizing for nanoseconds, or even milliseconds doesn't matter when the same operation also involves multiple database queries or API calls

The problem with that logic is that it’s pervasive: people have that same attitude everywhere even if no IO is being done. That’s how we get multi gigabyte processes.

The whole language (and Rails) also pushes you towards a less efficient path. For instance you’re probably iterating over those six plans and inserting them individually in the DB. Another approach would’ve been to accumulate all of them in memory then build and perform a single query. That’s not something people really consider because it’s “micro” optimization and makes the code look worse. But if you miss out on hundreds of these micro optimizations then you get a worse system.

In a general sense optimizing Ruby is indeed futile: any optimization is dwarfed by just choosing a different language.

I say all this as someone who has worked with it for two decades, I like the language, it’s just laughably inefficient.

radanskoric|3 months ago

Have you used it over the last few years? It has it been rapidly improving, mainly because Shopify put a team full time on it. It doesn’t take a lot of people to optimize a VM/interpreter it just has to be the right people.

And the question is always “fast enough for what?” Different languages are more suitable for different types of projects. I wouldn’t code a rendering engine in Ruby but for web apps it’s amazing.

boredtofears|3 months ago

> For instance you’re probably iterating over those six plans and inserting them individually in the DB. Another approach would’ve been to accumulate all of them in memory then build and perform a single query. That’s not something people really consider because it’s “micro” optimization and makes the code look worse.

This same pitfall exists in every language. This has nothing to do with Ruby.

whstl|3 months ago

This attitude towards wastefulness is how you have web apps that could run in a single machine but struggle to run in a server cluster.

And after a couple years even Postgres is struggling because the amount of queries is too massive because of abstractions that don’t lend themselves to optimization.

Also it’s how you have codebases that could be maintained by two or three suddenly needing dozens because the testing suite needs hours to run and people even celebrate when there’s no tests in sight.

Just anecdotal personal experience. But I saw this happening inside at least 4 successful companies that started with Rails but didn’t care about those problems, and ended up wanting/having to move to something else.

cortesoft|3 months ago

Again, though, these bottlenecks are because of how the system queries the database, not how methods are dispatched.

I agree on the ORM abstractions causing huge performance issues, but it has nothing to do with Ruby’s dynamic method declarations.

fny|3 months ago

The reality is most companies and products never blow bast the point of needed to ditch Rails. The argument made at the time was scaling horizontally is cheaper than hiring new devs, and you probably will never need to scale that much horizontally.

Test suite bloat is a different problem that stems from the lack of incremental typing which I think is what ultimately killed Ruby and Rails.

Any big Rails codebase can be a nightmare to grok unless people have been diligent about documenting what different methods return.

em-bee|3 months ago

i find this structure a bit odd. i would have gone for the following pattern:

    Billing::Plan.find_or_create_all_by_attrs!(
      standard => {1.month: 10, 1.year: 100},
      pro => {1.month: 50, 1.year: 500},
      enterprise => {1.month: 100, 1.year: 1000}
    )

brunosutic|3 months ago

This is supported and would work with no implementation changes. The "Friendly Attributes" idea is very flexible.

Just a small Ruby syntax correction for your example:

  Billing::Plan.find_or_create_all_by_attrs!(
    standard: {1.month => 10, 1.year => 100},
    ...
  )