Bad code is *very* scalable!

 Is your system scalable? As in, “does it get faster the more CPUs/Nodes you throw at it?” (no quibbling yet about “faster” please). 
The issue here is that when we think “scalable”, we immediately fall into the world of parallelization, concurrency, NUMA, etc. — in short, we tend to believe that our theory is solid, our code is excellent, and we’ve, at the very least, waved our hands in the direction of mechanical sympathy.
Is this actually true though? I don’t know about you, but in quite a few of the places I’ve been in, the theory is mostlysolid, the code is far from excellent, and mechanical sympathy is, well, something to be dealt with later. The sad truth is that when we say “scalability” we usually assume “efficient use of resources”. Beck is correct in putting “Fast” last, but (and this is where quibbling is important) “Fast” is another overloaded term. Do we mean throughput? Latency? Concurrent requests? Time to process a dataset?
The answer, of course, is all of the above, and also depends on what you are actually looking for. 
There are so many sins in this arena
 — GoogleThink: Where you plan for millions of requests per second, and build up this massive system/infrastructure with all this overhead, when a single redis instance might easily get you to the thousands that you actually see.
 — RealBadCode™: You have managed to hit O(n!) by processing your data with loops-in-loops-in-loops... Yes, your system scales horizontally, but lords, at what cost?(•)
 — WrongHardware: You developed your code on your quad-core/16GB laptop, and then proceed to deploy it on a t2.micro. What did you expect?
 — AssumptionHell: You test the f**k out of the system core, but all the ancillary features (storage, external data sources, input queues, whatnot) are mocked. Do you actually know what the impact of all this overhead is on your system?
The bottom line is that we really need to ask ourselves what we are trying to achieve when we mean “scalability”, why we want to go down any particular path, and internalize the answers…
(•) Another example from a recent paper by McSherry et al. — “any system can scale arbitrarily well with a sufficient lack of care in its implementation. The two scaling curves in Figure 1 present the scaling of a Naiad computation before (system A) and after (system B) a performance optimization is applied. The optimization, which removes parallelizable overheads, damages the apparent scalability despite resulting in improved performance in all configurations.”

Comments

Popular posts from this blog

Erlang, Binaries, and Garbage Collection (Sigh)

Spot The Difference — Deep Learning Edition