Autotuner: How to speed up your Rails app

(railsatscale.com)

183 points | by onnnon 10 days ago

5 comments

  • Alifatisk 9 days ago
    Github: https://github.com/Shopify/autotuner

    It’s incredible how much Shopify is investing in Rails (& Ruby for that matter).

    And I assumr the investment is paying off because otherwise they wouldn’t continue like this.

    • gregors 9 days ago
      I think it's also a by-product of the CEO starting the company in Rails, and now having top engineers being part of Ruby core team or Rails core team. To a certain degree they'r steering the Ruby/Rails ship technically.

      Why would they bother switching if Shopify isn't having fundamental problems and they're the tog dog in their stack?

    • bigEnotation 9 days ago
      I wonder what the break even point would be to just have switched to use JVM.
      • bastawhiz 9 days ago
        Stripe tried switching lots of code to the JVM and it was a huge disaster. Unless you already have lots of small services with clean interfaces and their own data stores that can be incrementally switched, you spend far more time bending over backwards to keep two systems running (one with some limited parity with the other) in tandem.

        The cost of running the system is almost never bottlenecked by the performance of the language itself, but rather the responsibilities of the system and cleanliness of the code. Plus, in the migration, you start incurring the cost of your Ruby code calling your JVM code (and vise versa; your systems are almost certainly not a DAG), which almost certainly has higher overhead than whatever speedup you'd get from running code in the JVM in the first place. And then you're sharing protobufs/thrift files/whatever between different languages and libraries of varying degrees of quality (good luck with those Ruby protobufs!).

        Before you know it, writing a little tool to optimize your Ruby garbage collector sounds like a really great idea.

        • parentheses 8 days ago
          Stripe and Shopify are such polar opposites. Stripes profit per web request is super high. Shopify has to monetize infrastructure efficiency.
      • ajmurmann 9 days ago
        The problem is the "just switching" typically means a full rewrite and has a ton of logistic challenges. Are you gonna higher an entire second team? What happens to feature work on the current system? If you keep going full-throttle on features, you'll never catch up. If you stop developing features for a prolonged time, you are putting your entire business at risk.

        Writing new services in Java might help, but still doesn't solve the main issue if your Rails app is a monolith. Breaking up the monolith might be a bad decision and is also super expensive and might even eat lots of the potential performance gains.

        • regularfry 9 days ago
          Rails on JRuby was a tenable proposition last I looked. Been a while though.
          • mdaniel 9 days ago
            I believe TruffleRuby <https://github.com/oracle/truffleruby> is the state of the art for Ruby on the JVM, and <https://news.ycombinator.com/item?id=33503622> says that Mastodon works on it, so that's one data point. I haven't worked up the emotional energy to try to get GitLab to run on it
          • ericb 9 days ago
            I was in a large org that did this for a while. It was extremely painful to be this far off the beaten path.

            When you stay in the well trod C Ruby path, you benefit from the hordes of others who cleared the landlines before you. With JRuby, not so.

          • norman784 9 days ago
            JRuby is far behind CRuby, so there are a lot of gems that you can't use, also there are not too many companies investing in JRuby itself, IMHO CRuby it's a safer bet.
          • rco8786 9 days ago
            Still around but it's significantly slower than stock Ruby.
      • ransom1538 9 days ago
        To save VM instance costs (not disks)? Probably never.
    • whalesalad 9 days ago
      sunk cost
  • andrewmutz 9 days ago
    I love to see how active and vibrant the Rails community is. I used to be concerned about the viability of building new companies in Rails, since the ruby share of languages is so low these days. Based on the still-healthy community and the ridiculous productivity level that a developer can have with Rails 7+ (turbo, morph, stimulus) I still think its a fantastic stack to build a company with.
    • atomicnumber3 9 days ago
      I normally interview in Java, partly because I know it's deepest demons, and partly because pretty much anywhere will let you interview in it.

      But recently I interviewed for a staff engineer position and there was a portion that was "API programming." Just writing a basic REST API to CRUD a model object. And I was like, oh my god, I know what I have to do. So I used rails. It was an hour and 15 minute block, and I ran the interviewer out of extensions to the problem after 30-40 mins. So we just chatted for 20 more and then both went to an early dinner.

      (Unfortunately I didn't get the job - they were hiring a staff engineer but afaict ended up downgrading the seat to a senior engineer spot (50% the total comp) and rejected me and the other guy who was interviewing for the staff spot.)

      But damn did I feel like I properly represented Ruby and rails in that one interview.

      • datascienced 9 days ago
        Maybe that was the problem, Rails and Ruby for this problem didn’t demonstrate enough challenge for the role, so it didn’t show you off enough in the interview.
        • sensanaty 9 days ago
          I actually had a similar thing happen to me, blazed thru a similar "design an API" type question flawlessly, but they didn't like that I didn't write up a lot of custom code for standard CRUD stuff...

          It's like they wanted me to overcomplicate things for some reason

        • inopinatus 9 days ago
          That could be framed as an interviewer skill issue. We're supposed to give the candidate space to demonstrate both their productivity and their talent. So if expecting a programmer to reveal their abstract thinking capacity through some complex domain-specific task, building a REST API for CRUD may not be the ideal vehicle, being so mundane as to lend itself unquestionably to off-the-shelf framework solutions almost any mature language.
        • atomicnumber3 9 days ago
          Eh maybe. But if they want someone who can wank off instead of ship things, then I don't know that I want to work there. And I'll never know since places don't give you feedback despite the time and interest you showed.
    • RowanH 9 days ago
      I would imagine with cutbacks on spending/investing I think people getting leaner and meaner will re-visit the sheer productivity you can get out of it.

      Sure shaving the last 10/10ths of having a SPA with simple API based back end gets the ultimate user experience and speed but that cost curve goes up significantly for that last 10th (if you were to compared to an 'old school' Rails app)

      I can't even fathom what it would have taken to build our startups' product in say React + Node (as an example..) vs OG Rails SSR. I look at a "sort of" competitor in our industry, and their rate of feature development is ridiculously slow by comparison.

      • rubymancer 9 days ago
        > I look at a "sort of" competitor in our industry, and their rate of feature development is ridiculously slow by comparison.

        Seconded. At my org, Ruby/Rails is our competitive advantage.

        Our 5-6 competitors are all Java/.NET shops -- we deliver fixes and new features dramatically faster and deploy them with ease. It gets noticed.

        The main downside is rails doesn't scale well re: complexity so regular refactors are necessary (ours is a high-volume big data app).

        For performance/cost, it took some doing but by strategically moving business logic to higher performance techs we've even managed to get to a great spot there.

        • RowanH 9 days ago
          While certainly a little polarising the adage of optimise later really comes into play here. We do a lightweight industry specific system that had all the generic stuff (eg time/tasks etc) with some special sauce that makes us stand out. One of our clients said "Mate the rate you guys are adding features - the ERP company we went with they haven't done 1/10th of what you've done in the last year. Can you implement full multi-level bills of materials? "

          I said "no, can't do that - that's huge".

          A weekend later of experimentation (thanks to one very kick-butt gem on that has an amazing way of managing trees) "actually, we may just be able to - it's going to be a long road though - setting expectations..."

          A period of time later we've now implemented a full BOM planning/tracking system, tested well upto and beyond the numbers of items these types of companies expect.

          To the point they cancelled their renewal with a big/established ERP vendor and went with us instead.

          There's definitely some instances where speed to market trumps everything else. We can go optimise queries later on.

          What's been fascinating is I left my day job 2 years ago (to the month). We've gone from unheard of to becoming the market leader in our space. There is absolutely no way that could have been done with any other stack (without spending 5x the money - and I argue that co-ordinating a bigger developer team it almost wouldn't matter what money you throw at it, it gets exponentially harder getting everyone on the same page for delivery).

          At my old workplace I couldn't convince the .NET team for love nor money to look outside the box.

          • neonsunset 9 days ago
            Because Ruby and especially RoR is a strict downgrade in every dimension compared to .NET. Now, these developers could have been using old .NET Framework, in which case we usually pretend they don’t exist because it’s like stubborn Python 2 of .NET that is otherwise the most productive platform for back-end (with really, really good performance).
            • RowanH 9 days ago
              > Because Ruby and especially RoR is a strict downgrade in every dimension compared to .NET.

              And that line of thinking is damaging in the tech world. There is no one ring to rule them all. Each tool, language, framework has a place - everything has tradeoffs.

              I've worked with enough .NET world to know what the tradeoffs would have been.

              For instance the critical library that enabled this piece of functionality, the nearest thing in .NET world looks to have 1 star on github, last updated 4 years ago. The ruby gem has 1.8k stars, tonnes of commits and upto date.

              So if you were to implement that in .NET you would be (a) hitting the books (b) re-writing that library or (c) doing a hugely in-effecient/naive implementation that wouldn't scale.

              In RoR land - drop in the gem and be prototyping that afternoon.

              Sure if I was VC backed, and had money to burn, it might be a bit more interesting to use .NET - if were targetting more enterprise oriented clients and potentially wanted an on prem option, then yeah - .NET. Wanting more access to developers in our country - .NET, that's the predominant market. Etc etc.

              In our use case RoR isn't a downgrade.

              • azurelake 9 days ago
                Curious what the gem is?
              • neonsunset 9 days ago
                Ruby is subjectively a worse language than C#, it has worse tooling (as testified by Ruby developers), worse expressiveness and, most of all, much worse performance.

                If there isn't an SDK for something in .NET but is in Ruby, it speaks for the poor quality of an engineering culture in that company (as it is likely they offer Java SDK at the same time). And even in that case, you can just generate a client from OpenAPI manifest. Or a gRPC client from .proto (even better). Or if it's an algorithm, you're much better positioned with all the low-level tools C# offers to write something performant with reasonable amount of effort.

                And even if that doesn't work, you can just call C bindings by using one of many existing binding generators or just `[LibraryImport]` the calls directly with little effort, after all, C# is a proper C language with C structs and pointers.

                But most importantly, you get robust results and consistently good performing application with no scalability issues, good build system and very little risk of accidentally breaking the codebase.

                And you don't need to make a developer productivity tradeoff in order to achieve that. I don't know when the bad reputation has to go away, but surely we're long past that point.

                • choilive 9 days ago
                  I will admit that the .NET ecosystem has gotten way better since being more friendly towards Linux users/environments and I used to code a lot of C#.

                  I love both Ruby and C# - I don't think one is better than the other. Ruby also has good interop with C. The performance of Ruby is good enough for most use cases. Scaling a Ruby app via multi-process scaling has worked perfectly fine without major issues for most use cases. The open-source 3rd party libraries in the Rails world have a certain "feel" to them.. as if they were written by devs that care a LOT about the - excuse the trendy term- DevEx that are often missing in the C# world.

                  Call it bias due to familiarity but Rails continues to remain the most productive option to bootstrap a web app/startup for me. Often I think most of the dissonance is simply due to difference in philosophy. Devs don't like Rails because its not "their way" and not that it is inherently better.

                  Pick the tools you like to use, most productive with, and most appropriate for the application - thats it. No need to nitpick on language semantics, tooling, or performance if those are not even major considerations for what you are building.

      • ecshafer 9 days ago
        If you haven't given Turbo and Stimulus a shot, I would recommend it. Way faster to write than React, and super fast and performant. I would say its definitely the way to go with Rails pages that aren't extremely simple.
        • adeeshaek 8 days ago
          Could you share the kinds of situations in which you've seen Stimulus and Turbo really shine?

          My team inherited a Rails app, which used Turbo and Stimulus and we really struggled to create UIs that matched our design team's vision. We eventually had to move to react + MUI just so that we could build a webapp with a modern look and feel.

          None of us come from a rails background, so I'm sure that a big part of our problem came from us trying to bend Rails to our will rather than embracing it - if you have any advice on articles / books that embody the rails approach, I'd be really grateful if you could share them.

          • ecshafer 7 days ago
            How Stimulus and Turbo work together, is basically this: Turbo lets you do partial page updates. Stimulus works a bit like a super light framework for UI only functionality (Toast messages, Error notices, etc). We have made both applications that are pretty stateful and more display and read only, and its way faster to both develop and run than React pages imo. Compared to standard ERB pages in Rails, where if you want to change some value on the page, you need to reload the whole page. Turbo lets you split these up into components with their own controllers, and views, and components. Then only reload the components you need to reload. So you end up with a lot more performance, a lot less redraws, and a lot less database activity for complicated pages.
        • nickjj 9 days ago
          Yep, and you can also use it with any stack. I've successfully used both with Flask.
        • RowanH 9 days ago
          Thanks! Definitely aiming to try them out
      • bdcravens 9 days ago
        I remember what happened in the early 2000s and how companies pulled back on the tech they were using. A few years ago I was convinced that fat front-end stacks are a luxury of companies with "free" money, and that the industry would be making tough choices. (To be clear, there are applications that the SPA approach is best for, but many applications are being built that could just as well be served by an old-school PHP and Jquery app)
        • gedy 9 days ago
          I feel like this opinion is a bit stale, many companies use tools like NextJS, and it's as productive as Rails and not what I'd call "fat". The biggest issue some folks have are there's no standard ORM yet (maybe Prisma), but ORMs are not so critical with node or js based apps imho.
          • bdcravens 9 days ago
            I do like how NextJS has done a good job of bridging the gap between SPAs and classical back-end apps (for example, file-based routing). My understanding (with limited experience) is that the deployment story is great for Vercel, and less so for other platforms (requiring you to own a lot of the build pipeline, which is one of the bigger pain points of modern JS)
          • realusername 8 days ago
            I struggle to see how you could maintain a large backend app without a good ORM to support it, that would be painful for sure
            • bdcravens 7 days ago
              It was done before ORM became en vogue using SQL and recordsets. When it got too hairy we'd just put an abstraction in place, similar to how many apps end up doing the same atop the ORM via service objects, etc.
              • realusername 7 days ago
                Yeah you always can but you end up with an in-house kind of ORM and those tend to not evolve too well in my experience.
    • bdcravens 9 days ago
      3-4 years ago I was convinced that Rails was in its sunset years. JS had all the energy, Ruby conferences were disappearing, and it seemed like there was no new open-source development happening: we were all just using the same gems we'd used for years.

      I'm happy to say that I was proven very wrong. New conferences have sprung up, over-the-wire is trending well against SPAs, and there's been a ton of new features and approaches that have kept Rails and Ruby very relevant to modern development.

      • techtalksweekly 8 days ago
        I'm running Tech Talks Weekly newsletter, so I'm following lots of various conferences. I must say Ruby/Rails community is increasingly active and growing after the pandemic. There are lots of conferences planned for this and the next year including RailsConf, Rails World, Baltic Ruby, and many more.
    • Syntaf 9 days ago
      From personal experience, I also appreciate that it's one of the easier stacks to keep updated with the latest and greatest. I've upgraded projects from sprocket-backed asset pipelines to bun in a couple days time, and the new tooling you get with modern rails really make upgrading worth it.

      Last year I started a new project[1] for a member management platform and really fell in love with the new jsbundling pipeline paired with stimulus, it feels like I've rekindled my passion that led me into programming initially; the ability to hack & prototype with rails is pretty unmatched (though it's worth mentioning Django holds a special place in my heart as well)

      [1] https://embolt.app

    • jupp0r 9 days ago
      Where do you get the idea that the rails ecosystem is striving? I work on a big Rails monolith as part of my day job and the amount of abandoned libraries in the ecosystem and general quality of libraries is pretty miserable if compared to Golang, Java, Python, JavaScript and others.

      I'm not saying it's a bad technology choice for a new company when all you need is to build a CRUD web app fast, but I wouldn't use it for anything that requires you to serve >1MB of JSON API responses or anything that requires concurrency, substantial IO, lots of API interactions with external services, low latencies, lots of memory or compute heavy computations, etc.

      • jupp0r 9 days ago
        Just to give you a concrete example:

        We use grape-api for some of our API endpoints. I needed to set some custom cache headers for some GET API responses and was looking into gems that do that for grape. They have a list of 6 libraries in their docs [1] that they recommend.

        Their newest commits were 4, 9, 9, 10, 8 and 9 years ago, respectively. This is just one example, but I would bet half of the libraries in our transitive dependency tree haven't seen any maintenance in this decade.

        https://www.ruby-grape.org/projects/ [1]

      • Syntaf 9 days ago
        Rails is *ancient* in the context of tech though, I think it's fair to criticize the skeletons in the closest while not necessarily refuting that the ecosystem is still active.

        An equivalent example imo is the PHP ecosystem, which itself has been growing rapidly and thriving over the years -- but at the same time if you did deep enough you'll find a graveyard of long since abandoned frameworks, libraries, etc...

        • jupp0r 9 days ago
          I think both PHP and Ruby still have and will keep their niches, but in my opinion they don't provide the building blocks to expand outside of their niche and grow much at this point. If you contrast that with let's say Rust, which at least has the potential to become successful across a wide field of applications.

          The problem that I can see with Ruby in particular is that its niche is getting smaller and smaller as the world evolves around it. Interactions with external services that are on the critical path to serving requests are becoming more common. Interactions with actual contents of pictures and documents are becoming more common. Concurrency is a major missing building block to build modern apps compared to 10 years ago, and the answer of the Rails community has mainly been YAGNI (although there are efforts to incrementally improve things, but no fundamental shift in language or runtime design).

          • PedroBatista 8 days ago
            Brother, did you just called PHP a niche and offered a prognosis on how they might be able to keep it? :)

            And then talked about Rust as it was a general purpose language that all the potential to become the top language for most programming in the World?

            I’m joshin’ but seriously, PHP is HUGE and Ruby was always small even when they were loud on the internet.

            Rust is a systems language currently being used as a big hammer for everything and a somewhat obnoxious community just as Ruby, then Node, then Go were when their day in the Sun was.

            I’ve seen the exact template of your comment throughout the years, it fine, it belongs to this particular point in time and in your of the woods, there are more.

          • choilive 9 days ago
            Ruby introduced language native fibers and actors since 3.0 and they work pretty well. Concurrency could still be better but I'm with the YAGNI crowd - unless you are building something that requires a ton of async you probably won't need it. If you do need it, there are admittedly better tools for the job.
    • princevegeta89 9 days ago
      Ruby is incredible. It is still one of the best choices for a platform to build a company or a product quickly with. If it cannot keep up with your scale, throw more hardware at it and it will still be worth it in terms of time and man-hours saved.

      I only ever wanted compile-time linting and better autocompletion such as in the case of Elixir LS. Does something like that exist for Ruby now? How is Crystal these days?

      • TobiasBales 9 days ago
        There is ruby-lsp and ruby-lsp-rails. For the former to shine you do need to use sorbet but for any moderate to large sized rails app I'd personally recommend it anyway. Yes it's not perfect, yes it has a learning curve but boy does it make refactoring easier, faster and safer.

        ruby-lsp-rails builds on top of that and hands out information on models and routes mostly

        • pqdbr 9 days ago
          Also using ruby-lsp with VS Code and it's been a game-changer.
          • Lio 8 days ago
            I'm using ruby-lsp and DAP with NeoVim and I know others using it with emacs so ruby-lsp really is a great boon to the community.
      • Lio 8 days ago
        Autocompletion is getting much improved.

        In the latest version of IRB for example they can use RBS based static typing for autocompletion[1].

        This gives me a lot of hope that we'll have a more widely used static typing solution soon. i.e. some coming together of Sorbet, Steep and RBS.

        1. https://github.com/ruby/irb?tab=readme-ov-file#type-based-co...

    • inopinatus 9 days ago
      The only gripe I have with the Ruby ecosystem (and transitively to Rails) is that RubyGems is not curated, and many gems have bitrotted into broken obsolescence over the years, but these are presented with equal standing to those that are actively maintained, and it takes a discerning eye & additional effort to tell the abandoned ones apart from packages that are simply very stable.

      There’s also a ton of idea placeholder and half-baked proof-of-concept gems. These are easier to spot (usually released once, years ago) but are now nothing but squatters on the namespace.

      Even if human effort is too much to ask, a filtered subset of packages that successfully bundle and pass their own tests for specific Ruby version+arch would be helpful. More broadly, perhaps that RubyGems should even be entirely siloed for each annual Ruby release, since this tends to be the boundary of breaking changes to the language (see also: semver) and approximately the cycle on which unmaintained packages become an obstacle to the update of shared dependencies.

      • graypegg 9 days ago
        https://www.ruby-toolbox.com/ If you’d like a list of maintained gems! They even show activity stats for each gem.
        • inopinatus 9 days ago
          Yes - Ruby Toolbox is handy, one of the discovery and currency assessment tools I use too, and is good at surfacing projects that are actively developed, but it takes a metric driven approach that's intrinsically weak at distinguishing between abandoned code and stable code. It won't reveal when a decaying gem will cause other dependencies to be held back, and Ruby Toolbox suffers from the same fundamental blindness to compatibility with specific language editions that RubyGems has. Since it’s not a part of RubyGems, it ultimately can't offer a reliable barrier to inadvertently installing bitrotted code.

          None of this is meant as a criticism of Ruby Toolbox, because it never claimed to do all that, nor can we expect it to. All said & done, and to reframe things more constructively, I think there's a missing piece in the community infrastructure puzzle that someone could fill if they had the time, inclination, and build farm to do it.

    • selykg 9 days ago
      This thread seems to be getting some views. I'm looking to break into the Rails work, but it seems rough trying to get into a job doing Rails work as a junior, not quite senior role. I have other development experience, primarily in Ruby and Objective-C.

      Any advice? I know the job market is a bit of a rough one right now as well.

      • sensanaty 8 days ago
        For Juniors it's tough (in general, though it's always been tougher in rubyland), because even the most well organized codebases tend to turn into a bit of dynamic magic spaghetti that can be hard to follow if you're not familiar with Ruby's dynamic nature. Getting newcomers to the language/framework onboarded to old projects (and most Rails projects will be old ones these days) can be a bit of a mess and take a lot of time and effort, so a lot of companies are weary of getting juniors.

        That said, if you can display you have knowledge of the more important Rails libraries like ActiveRecord, ActiveJob, how Rails handles the MVC pattern etc., then your chances are much better. It's a bit of a magical framework when you first start working with it, so it's important to know what it does behind the scenes, at least a tiny bit, since otherwise it's easy to get lost.

      • adeeshaek 8 days ago
        If you are looking to become more competitive as a candidate, I strongly recommend that you look at one of the more popular languages / frameworks instead of focusing on Ruby on Rails.

        Despite the major investment made by Stripe and Shopify, my experience is similar to that of this commenter: https://news.ycombinator.com/item?id=40161561 - like them, I've found the open source libraries available in the Ruby + Rails ecosystem to be aging and less well supported than that of more popular languages / frameworks like GoLang / Java / Python.

        Rails is delightful to work in and very thoughtfully constructed, and the Rails community is helpful and welcoming. However, if your priority is to maximize your chances at getting hired, I would look towards GoLang / Java / Python etc, which are far less enjoyable to work in but far easier to find jobs for.

        Best of luck!

      • Lio 8 days ago
        My advice would be to either start contributing to an existing FOSS ruby gem or to create your own for some specific purpose.

        That will allow you get familiar with the ecosystem so that you can hit the ground running and also allow you to point to experience during the screen and interview phases.

    • x0x0 9 days ago
      with hotwire, rails is nearly a superpower. 90% of what react gives you at a tiny fraction of the dev time costs.
      • xutopia 9 days ago
        And a fraction of initial load time... and HTML rendered on first load without adding anything to the framework.
  • daviding 9 days ago
    I tried this and couldn't get it to work on a Rail 7.1 Ruby 3.2, no output. The readme.md could do with some examples of what sort of recommendations come out. Edit: it outputs metric, just no recommendations so moving on.
  • kristianp 9 days ago
    To provide some detail if you haven't clicked, it tunes the Ruby garbage collector based on runtime behaviour.
  • Didah 9 days ago
    Is there something similar for flask apps that anyone knows of?