chapter eleven

11 Diagnostics

 

This chapter covers:

  • Surveying the diagnostic signals
  • Detecting memory leaks through a systematic flow
  • Distinguishing garbage collection pressure from memory leaks
  • Diagnosing CPU bottlenecks and event loop delays
  • Introducing event loop utilization as a scaling
  • Reasoning about performance problems when the diagnostic tools are unavailable

In one of my old consulting jobs, I was asked to come out and help the customer figure out why their application was performing so poorly. They were being plagued by terrible throughput, high latency, and memory issues that were driving up their infrastructure costs. In my initial consultation with them their lead architect walked me over to a giant monitor they had set up that displayed the real time metrics they were collecting. It was a screen full of graphs and meters and logs. After a very brief orientation he said, “If you can look at this board and tell me what problem we’re having, I’ll hire your team to help us out.”

It was a bit of a ridiculous request given that I had not yet looked at a single line of their code, but I humored him and stared at the board for a couple minutes. One graph stood out immediately. It was the memory heap usage. It would steadily climb, hit a max, hold for 30 seconds, then drop suddenly. Climb. Hold for 30 seconds. Drop. The pattern was clear.

11.1 The diagnostic signal landscape

11.1.1 process.memoryUsage()

11.1.2 process.resourceUsage()

11.1.3 Chrome DevTools

11.1.4 Heap snapshots

11.1.5 Garbage collection tracing

11.1.6 CPU profiling

11.1.7 Deoptimization tracing

11.1.8 Event loop delay

11.1.9 I/O latency

11.1.10 Thread pool saturation

11.2 Detecting a memory leak

11.2.1 Step 1: Confirm the symptom

11.2.2 Step 2: Distinguish leak from pressure

11.2.3 Step 3: Find what is accumulating

11.2.4 Step 4: Find why it is retained

11.2.5 Finding the source of pressure

11.2.6 Reducing pressure

11.3 Finding CPU bottlenecks

11.3.1 Confirming which problem you have

11.3.2 Finding the hot function

11.4 Utilization as a signal

11.4.1 Why CPU utilization misleads

11.4.2 Event loop utilization

11.4.3 Reading ELU alongside CPU

11.4.4 ELU for scaling decisions

11.4.5 Does ELU translate to other runtimes?

11.5 The mental model as a diagnostic tool

11.6 Summary