Copy
You're reading the Ruby/Rails performance newsletter by Speedshop.

The Rails Performance Workshop was released this month.

Stop guessing. Usually, you're not very good at it.

In working with dozens of companies and hundreds of Rubyists over the years, I've learned that many performance misconceptions arise because programmers have an incomplete and surface-level understanding of their own systems. That is to say, most programmers only understand "the tip of the iceberg" as to what their program actually does when it completes an operation, like a controller action or a background job.

I'm not even talking about the multiple layers of the stack involved. Yes, of course, Rubyists generally don't understand cacheline alignment, for example. But I'm talking about something much more basic: they don't understand what Ruby code is actually executed when a request or job is completed.

Some of this is caused by the sheer complexity of our own applications. It's simply not possible for a single programmer to understand what a 100,000 line application is doing 100% of the time. Modern mega-monoliths, like Shopify, easily stretch into the millions of lines.

Another cause is the complexity of our dependencies. You've got 100,000 lines of code you or your team wrote, but if you added up all the lines of code included by Bundler, what would that add up to? A million or more?

Applications are a bit like icebergs: you only see the very top. An individual developer's attention generally focuses only on the 10% of the application that they recently wrote code in. This causes problems when developers try to solve performance issues without proper measurement.

The most common place I see this mistake is easily serialization (usually of JSON) in API applications. In these apps, developers are generally familiar with the serialization code. Everybody on the team has probably written or interacted with a serializer or JSON template at some point.

Yet, when I first talk to these teams about performance, everyone assumes performance issues are either the fault of the serialization library ("What if we used Active Model Serializers instead?") or the actual JSON library ("what if we used OJ instead?").

And every time, when we actually profile the app in production or in development, neither of these libraries matters at all. Sometimes it's another dependency or part of the app, called 100 times in an index action, that's slow. Most of the time it's data loading problems: too many SQL queries or just plain N+1s.

I'm sure it's also partly caused by a natural bias to blame one's tools rather than one's own code. Most people are happy to believe in a silver-bullet switch to a new techincal approach rather than actually do the work of measuring performance through a profile.

And that's what I'm really trying to get at here: you can't guess, you have to profile. Profiling is the final answer, the last authority, the way that we can flip over the iceberg and see what's actually going on down there. Profiles, whether collected through your APM agent (like Datadog), or locally through rack-mini-profiler/stackprof, actually measure where the code spends its time.

So stop guessing. Flip over the iceberg, and open up your profiler.

Simply having one installed is usually the first step. Everyone should be using an application performance monitoring service, and as I've mentioned in other newsletters, everyone should also be running rack-mini-profiler in production.

Obviously, this is something I've covered extensively in the new Rails Performance Workshop. Why not give it a try?

Until next week,

-Nate
You can share this email with this permalink: https://mailchi.mp/railsspeed/flipping-the-iceberg?e=[UNIQID]

Copyright © 2020 Nate Berkopec, All rights reserved.


Want to change how you receive these emails?
You can update your preferences or unsubscribe from this list.