Skip to content

Instantly share code, notes, and snippets.

@tmcw
Last active February 14, 2021 14:38
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tmcw/4f9334f423a9294a965caed1c2deefb4 to your computer and use it in GitHub Desktop.
Save tmcw/4f9334f423a9294a965caed1c2deefb4 to your computer and use it in GitHub Desktop.
Optimization

Optimization

Correctly prioritizing and targeting performance problems and optimization opportunities is one of the hardest things to master in programming. There are a lot of ways to do it wrong: by prematurely optimizing non-bottlenecks, or preferring fast solutions to clear solutions, or measuring problems incorrectly.

I'll try to summarize what I've learned about doing this right.

First, don't optimize until there's an issue. And issues should be defined as application issues: performance problems that are either detectable by the users (lag) or endanger the platform – i.e. problems that cause downtime, like out-of-memory issues. Until there's an issue, don't think about peformance at all: just solve the problem at hand, which is "creating value for the end-user," or some less-corporate translation of the same.

Second, only optimize with instruments. By instruments, I mean technology that lets you decipher which sub-part of the stack is the bottleneck. Let's say you see slowness around fetching user objects. Knowing whether that lag is due to the SQL fetch, serializing GraphQL responses, network lag, faulty server middleware, or something else entirely is completely unknowable without looking, and guessing in this situation is actively harmful. So the focus first is on learning instrumentation. For JavaScript applications, this mostly means browser development tools and sourcemap analyzers. For SQL, this is the slow query log and things like EXPLAIN ANALYZE queries. For Rust, this might be Instruments.app or dtrace: our first priority in terms of Rust is learning the instrumentation stack (and hoping to G-d that those tools are good).

Third: premature optimization is evil because optimized code is worse, not because of the time it takes to write. Premature optimization is evil because optimized code is typically less readable, maintainable, and safe than unoptimized code. For example, mutation is – in most languages – much faster than immutable operations like Array.map. But on the other hand, it's harder to test, easier to get wrong, and less safe to use. The mental overhead of remembering that something will be mutated and that a function is not pure and idempotent is significant and costs you for as long as that code survives.

Fourth: prefer certain kinds of optimizations. Language-level optimizations are popular because they're easy to blog about and fun to learn about.

For example, for some period of time, JavaScript intepreters didn't cache array lengths, so for (var i = 0, len = arr.length; i < len; i++) was slightly faster than for (var i = 0; i < arr.len; i++). Lots of developers heeded the blog posts and followed that pattern. Then the interpreters optimized loops with array bounds checking and… the patterns became equal, and for some implementations the 'cached length' version became slower!

Language-level optimizations are very unlikely to affect overall performance. Mentally, I have a hierarchy of optimization strategies. Roughly:

  1. Removal. The best optimization is not doing an operation. For example, code that manually iterates through an array to count its elements when the language has a pre-calculated count available.
  2. Mistakes. A broad category of 'whoops' mistakes that are usually the culprit of early-stage optimization.
  3. Algorithms & network. Basically what is discussed in the 'mature optimization handbook' - starting with network operations (which are usually the slowest part of applications), then working down to algorithms, like unnecessary use of array searches when you could use a hash with O(nlogn)'ish performance.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment