I’ve been writing technical documentation and editing engineering articles for around fifteen years. In that time, jargon came and went. I fought the good fight, trying to keep writing about software engineering as free from unnecessary jargon as possible. About five years ago, I started seeing “performant” show up in drafts, as in, “This will result in performant code.” It kept showing up, and eventually I caved and let it through. I had to admit that maybe the word serves a purpose.
Now that I’m reading developer-centric content full-time and seeing the word day-in, day-out, I caught myself. When developers say something is performant, what exactly do they mean? And what can you do to make your app more performant? In the end, does it really matter?
In this article, we’ll take a look at what performant means, if anything, and where the performance of your code actually matters.
What do you mean, performant?
Performance always implies a measurement. For an application to be performant, you have to figure out what your metric is. Jeremiah Peschka, staff software developer here at Stack Overflow, put it in an analogy. “A Ferrari is ‘better’ than a Prius on the ‘goes fast’ metric, but the Prius is ‘better’ on the ‘I can carry more than a loaf of bread and a pack of gum’ metric.”
It’s about the quality attributes you can measure for success.
For the sake of argument, let's say you define performant as “runs fast” with a little bit of reliability to it. You can create a performant application with proper design and architecture with some optimized code to match. So what’s proper design and architecture? Whatever makes your application “performant.” Vinko Vrsalovic, senior software engineer here at Stack Overflow, says, “It's all a matter of definitions. If you mean performant as in it's able to deliver the load it needs to deliver now and offer paths to deliver more when the requirement changes, then whatever enables you to do that is what makes an application performant.”
That, friends and neighbors, brings us back to one of the key phrases of software engineering: it depends. Performant is whatever keeps your users from complaining about the application. And you have a lot of options with how you configure an application depending on what you want to optimize. Stack Overflow Staff Software Engineer John Wright puts it thusly: “As with most things software/IT, there are so many knobs you can turn to impact how something runs, and you can move several knobs to get the same impact. Speed up code. Speed up hardware. Lower network latency. Add caching to remove lookup latency. Remove caching to reduce memory usage. Add a server to the pool to increase throughput. Remove a server from the pool to decrease costs.”
Hardware and application load can change how something that’s been tuned to be fast to something that barely works. Imagine an app that handles one user's request under 20ms or handles 100 users' requests within two minutes. You don’t have to imagine it that hard; Stack Overflow, optimized for performance as it has been, was optimized for specific hardware. Wright says, “Stack Overflow is ‘performant’ on our current hardware, but if we moved the webservers, db and redis into a cloud vendor, the same code would likely fall over—at least no longer be ‘performant’.”
When engineers throw out the word “performant,” they may mean to emphasize the various metric improvements that code optimization, latency reduction, and hardware utilization all provide. But when someone trying to sell you something says “performant,” maybe that’s when you should be more wary. “‘Performant’ is a weasel word; it doesn't really mean anything more that ‘this thing works effectively.’” says Peschka. “Technically my shoe is performant at hammering nails into drywall.”
There are a lot of areas in software engineering where performance isn’t important at all. Stack Overflow Senior Systems Engineer Brian Artschwager—corporate IT, not a developer—says, “In IT, it doen’t really matter how fast most of our tooling and scripts run. We are concerned about completing/reproducibility. So sure, you could add a caching layer and over complicate it. Or, what you assume is running instantly may only sync occasionally on a schedule. There are so many things IT has that use a for loop at the scale of a couple hundred users/records, even a couple thousand.” Performance is a feature, and not every application needs performance.
There are, however, two types of application where performance does actually matter, and it’s because those applications have very specifically defined metrics around what performance means.
To the Lighthouse
For web applications, good performance can mean better placement in search results and the difference between a user making a purchase or click their Back button. I spoke with Lee Robinson, director of developer relations at Vercel, who thinks a lot about performance but is wary of the word performant. “It sets off the alarms in my engineering brain. Whether intentionally or unintentionally, it shifted to be more of a marketing word than an engineering word. I think the word performance should be rooted in engineering.”
Web users have very specific complaints about performance: slow page loads and content that shifts around; fortunately, web developers have ways of measuring performance that goes beyond vanity metrics: the core web vitals. These metrics come from initiatives by Google to measure the performance of web pages as part of determining the best search results to highlight. Google’s Lighthouse tool makes it easy to monitor these metrics. “Core web vitals has given us vocabulary and lingo to measure and talk about front-end application performance in a consistent way with a side effect of it being used to dictate or influence Google search ranking,” said Robinson.
Web sites today are composed of so many moving parts that having a specific set of terms that can accurately pinpoint performance and user experience issues can help developers pick the right pathways to optimize. These vitals are built around how the end user experiences the site, which can vary between people. Instead of tweaking the framework, maybe it’s time to find a better content delivery network (CDN). “If the site can't even load, we haven't got to the part where we can talk about layout shift on the page,” said Robinson. “We're just trying to get it to load within ten seconds.”
While the core web vitals have simplified how to assess performance on web applications, improving performance can still be an individual battle. The tools developers use to build sites are varied, and the sites they build can seem deceptively simple. “I like to call this the iceberg of web performance,” said Robinson. “Oh, it's just an eCommerce page with a couple product images and a Buy Now button. Then you look at the code and find 14 third-party scripts loading.”
There are a few things you can do to actually improve performance across the board. You can optimize your images and use modern formats. You can optimize how you use and deliver your brand fonts. You can lazy load everything outside of the browser viewport.
But Robinson cautions against what he calls Lighthouse whackamole: you knock down a performance issue and improve Lighthouse scores, and new ones will pop up in an endless cycle. Bumping a score from 98 to 99 probably won’t have a meaningful business impact, and may actually have a negative impact if you are draining engineering resources away from valuable new features.
So where are the meaningful metrics that can highlight areas to optimize. Robinson says to focus on core web vitals for actual users in the field, not just those on the engineering team’s machines. “By looking at the field data, we're seeing how real customers on real devices with varying internet speeds are actually experiencing the website.” It would be expensive to build a large browser network that tests speed in various conditions around the world, but you don’t have to. Google provides the Chrome UX report (CrUX) as part of its Data Studio.
There’s another industry where performance really matters. Performance boils down to a single metric that can be life or death for the user (though hopefully they saved their game nearby).
Games do it 60 times per second
Where applications and web apps will run some code in response to user input, many games are constantly receiving input and have to respond fast enough to maintain 60 frames per second (FPS) on screen. The FPS metric is king of the gaming industry and strongly affects user experience. Some gamers spend hundreds (even thousands) of US dollars to get better graphics cards that improve their ability to maintain hight frame rates.
Players will notice game code that performs poorly and takes extra time. Some routines are invoked hundreds of times per frame, so any extra speed a developer can squeeze out makes a difference. The video game industry is extremely competitive, and so those extra milliseconds saved can be applied to improved enemy behavior or fancy graphics. Even something with limited graphics like Dwarf Fortress has to optimize script behaviors when hundreds of actors are trying to pathfind over a malleable 3D space.
I spoke to Rob Oates, an industry veteran who is currently the senior director of technology and partnerships at Exploding Kittens, about why performance matters for games. “When I first got into the industry, we were still writing our own C/C++ memory arenas and hand-tuning assembly for math inlines. Every microsecond we shaved off of some critical inner loop would free up milliseconds we could spend on something more interesting like AI or graphical complexity without dropping the frame rate.”
Game development differs from other programming tasks in that it runs a game engine, usually written in a low-level language, that may be ported to multiple hardware systems. To allow for rapid changes without recompiling (or even closing the game), mod support, and a number of other reasons, many games use a scripting language that interfaces with the compiled game engine. As script languages are interpreted at runtime, this can be a source of slowdowns.
“I once saw a developer loop over a few thousand objects in a script and then call a native function on each object,” said Oates. “Crossing the script-native boundary was painfully slow, so this bit of game code would cause a visible hitch every time it was called. The solution was to hoist the entire function/loop out of script and into native code (which extended the scripting language), and make it a single cross-boundary call.”
If you’re creating games for a PC, then you can push back a little on hardware requirements if you think your game needs it. But if you’re targeting video game consoles, then you have a precisely defined pool of hardware resources. Little changes can free up precious resources to maximize FPS.
“We were working on a Wii title and a scripter added a new field to a table with hundreds, maybe thousands of records. Suddenly, we were busting the memory budget on the development hardware kit by a huge margin. The new field took the total number of fields in that table from 8 to 9. Following a hunch, I cracked open the scripting language source and checked how its memory allocator worked. Sure enough, it was set to only allocate blocks in powers of two, so adding one field was doubling the total amount of memory reserved for the table. That allocation strategy is good for performance if you intend to append items to a table, avoiding frequent reallocations. But we were using the tables primarily for reads, and almost never for writes once they were created. So I modified the scripting language to allocate the exact amount of memory required. We squeezed everything back into the dev kit's 64 megs of RAM and had room to spare.”
Commercial game engines have outsourced a lot of the low-level optimization tasks to the companies behind Unity and Unreal. Game designers today can avoid knowing anything about things like algorithmic complexity, memory management, and assembly. But that doesn’t mean these off-the-shelf game engines insulate developers from performance issues. “If you do not understand how memory works,” Oates said. “you can generate a lot of excess garbage and trigger frequent pauses for garbage collection. Or if you are working with reference counted objects, you can leak ‘islands’ in memory with circular references even with fully managed memory.”
Looking at this list of badly-optimized games, many of the top offenders are highly rated by users and were top sellers. So poor performance isn’t a death sentence for a game, though I personally avoided playing GTA V online because of its slow loading times (which an enterprising player managed to fix seven years after release). The deciding factor for most gamers is features and fun, as technical problems can sometimes be designed around. Games have become popular despite the creators’ lack of technical ability.
But that doesn’t mean a developer who wants a career in the video game industry should ignore the low-level knowledge required to optimize for performance. “I believe that a programmer who does not understand how to do this sort of thing today is putting a ceiling on their career advancement in large professional teams and projects,” said Oates. “Which is ironic, because the ability to do all of this was once tested for in junior-level interviews.”
Know your metrics and improve those
Overall, it seems my gut feeling was right: “performant” isn’t a very good word to describe software and programming concerns. It might even be one of those words that marketing loves to use because it means different things to different readers. Application performance, though, still matters, but why it matters depends on the effects on your users.
The industries where performance matters use very specific metrics to gauge what performance means. Whether it’s Largest Contentful Paint (LCP) or frames per second, the best performance metrics are tied directly to user experiences. Instead of trying to optimize blindly, find your application’s most important metrics and focus on those. Let your marketing team figure out how to talk about the results.