About a year ago I got a chance to start taking a course called Ascend with Steve Brownlee. We actually ended in May, but it usually takes me some time to process the benefits of something and I wanted to make sure I gave enough time to fully develop my thoughts about it.
Ascend is a 3-tiered program for Junior Developers who want to know more and level up. The tier 1 cohort covered shell scripting, SQL optimization, Django deployment, Django serializers, Docker, load balancing (and probably some aspects I can’t remember), but I’ll focus here on Docker and optimization.
Our SQL optimization dealt with finding bottlenecks in joins, mostly by replacing parts of the serializer with raw SQL and optimizing on that. As a byproduct, I took away the thought processes of optimization and scaling, so I began to apply those more at work and found about 20 different ways to optimize C# ranging from indexes, to asynchronous programming, to streaming, not to mention precomputing expensive loads, caching, and decoupling and calling APIs separately.
Where I look first
That thought process is the part that transferred. The layers below are the order I work through when something is slow, and what I have actually found at each one.
| Layer | What I go looking for |
|---|---|
| query shape | N+1 loops, and joins fanning out into a cartesian product |
| storage | Missing indexes |
| transport | Synchronous work made asynchronous; responses streamed rather than buffered |
| serialization | JSON objects decoupled from what they were dragging along |
| allocation | out variables on dictionary lookups, instead of probing the same key twice |
| caching | Redis cache-aside in front of reads that had not changed |
None of that is exotic. The useful part is having an order to check them in, so the answer is never just ‘increase the timeout’.