Analyze two small routines with n = 4: a double loop over a 4-by-4 grid, and a loop whose inner range halves each pass. Name the input size n and count one basic step, a single comparison or array read, per body run.
1. Choose the input-size measure
For the grid, n is the side length, so the input holds n × n = 16 cells. For the halving loop, n is the starting range. Every other cost will be written as a function of this n.
2. Count primitive operations
The grid body does one comparison per cell. Walk the rows: row 0 runs 4 times, row 1 runs 4 times, row 2 runs 4 times, row 3 runs 4 times. That is 4 + 4 + 4 + 4 = 16 body runs for n = 4.
3. Compose repeated work
Independent nested loops multiply: n outer iterations times n inner iterations gives n-squared total. When the inner range halves (8 → 4 → 2 → 1), ranges shrink instead of repeating, so add the passes: about log n of them, giving n log n when an outer loop of n wraps a halving inner loop.
4. Separate growth cases
The grid always visits all 16 cells: best, average, and worst case coincide at O(n-squared). The halving loop's ceiling over all inputs is its worst case; an average case would need a distribution over inputs, and an amortized bound would average a whole sequence such as repeated appends with rare copies.
5. Compare with the workload
n-squared against n log n decides scaling: doubling n quadruples grid work but only slightly more than doubles the halving loop's work. Constants still matter for small n, which is why a scan can beat binary search on tiny arrays. For the full method, continue with Complexity and Analysis.
Hardware, runtime, and observability notes
When tracing Trace Counting Steps on a 4-by-4 Grid in a live production environment (subsystem: execution, primary layer: runtime), keep the following step-level cost model and diagnostic checklist in mind:
- Step 1 (runtime): Choose the input-size measure — verifies state invariants before advancing the execution pointer.
- Step 2 (runtime): Count primitive operations — verifies state invariants before advancing the execution pointer.
- Step 3 (runtime): Compose repeated work — verifies state invariants before advancing the execution pointer.
- Step 4 (runtime): Separate growth cases — verifies state invariants before advancing the execution pointer.
- Step 5 (runtime): Compare with the workload — verifies state invariants before advancing the execution pointer.
Every transition across the runtime boundary carries both a direct CPU/memory cost (cache-line fills, descriptor lookups, lock acquisitions, or context switches) and a tail-latency queueing risk under contention. To verify this trace on your own service, capture latency histograms and hardware/kernel counters across each step boundary, compare cold-cache versus warm-cache execution paths, and confirm that error or timeout branches release all acquired descriptors, locks, and buffers cleanly.