Big-O explorer and benchmark
Compare growth curves, see how big an input fits a time budget, benchmark your own JavaScript to find its complexity class, look things up in a colour-coded Big-O cheat sheet, watch sorting algorithms run, and see where the costs come from: Fibonacci call trees, recursion trees, binary-search halving, and amortised appends — and why attention is O(N²) in context length, what an SSM's O(N) buys, and what a KV cache saves. Then revise for interviews: name the complexity of code snippets, drill data-structure operation costs, and solve recurrences with the master theorem.
Added · updated 29 October 2026
Works with
- Coding interviews Interview preppractise the patterns whose complexity you revise here
- Spaced-repetition flashcards Mathematicsthe Big-O and data structures deck for spaced review
How to use it
⛶ Full screen (or F) gives the open tab’s picture the whole screen — the growth curves, the
benchmark fit, the sorting bars, the Fibonacci call tree or the attention chart — using the
browser’s full screen where it is allowed, otherwise a full-window layer (iPhone). The picture is
redrawn as tall as the screen allows, with its controls above it; Escape leaves.
Growth curves plots O(1), O(log n), O(√n), O(n), O(n log n), O(n²), O(n³), O(2ⁿ), and O(n!) together, plus two adjustable curves for a growth race: nᵏ (slide k from 1 to 10) and bⁿ (type b, from 1.001 to 3). Tick the classes to compare and pick how far n goes. Switch between linear, log-y (an exponential becomes a straight line) and log-log axes (every power nᵏ becomes a straight line of slope k). With both race curves shown, the tool says where bⁿ overtakes nᵏ for good — for 1.01ⁿ against n³ that is n = 2,339 — comparing n ln b with k ln n so nothing overflows.
Time & budget turns the classes into wall-clock time. Set a speed in simple operations per second (about 10^8 for a JavaScript or C loop, 10^6 for interpreted Python) and a budget; the table gives the largest n each class can handle, and how long each takes at the sizes you list. At 10^9 operations per second, one second is enough for n = 10^9 linear steps, n ≈ 31,600 for quadratic, n = 29 for 2ⁿ, and n = 12 for n!. Factorials and powers are computed with logarithms, so even 1000! has a time (in multiples of the age of the universe). The budget buttons run from 1 ms to 1 year.
Benchmark & fit times real code. Write setup(n) to build the input — it is not timed — and
run(input, n), which is. The tool runs in a background worker, for each size repeating
run until a batch takes at least 20 ms, and keeps the median of five batches. It then fits
time ≈ a + c·g(n) for every class, weighting each point by its relative error, and reports:
-
the best class, with its RMS error — when two classes fit within about 10%, the slower-growing one wins, because an extra log factor can always soak up a little timing noise;
-
the empirical exponent — the slope of log time against log n over the larger sizes, so n^1.02 is linear and n^1.98 quadratic;
-
the fitted model for each class, the raw timings, and a CSV to copy.
Examples cover summing an array, the built-in sort, all-pairs loops, binary search, Map
lookups, naive Fibonacci, bubble sort, and matrix multiplication. To get clean results, use a
range of n that spans at least two orders of magnitude, and make the work grow with n: a
benchmark whose run takes a few nanoseconds is dominated by loop overhead and the JIT. If run
changes its input (sorting in place, say), copy it first — every repetition reuses the same
input. Stop ends a run early; any size that takes over 20 s stops the run automatically.
Cheat sheet is a colour-coded reference in the style of the well-known Big-O cheat sheet: the complexity chart (operations against elements, from excellent to horrible), then average and worst-case costs of operations on arrays, stacks, queues, linked lists, skip lists, hash tables, BSTs, Cartesian trees, B-trees, red-black, splay, and AVL trees, k-d trees, and tries; heap operations (binary, binomial, Fibonacci, pairing, Brodal); array sorting algorithms (best, average, worst, space, stability); graph algorithms; and other common algorithms. Θ marks the typical bound, O the worst case, Ω the best case. Values follow CLRS and Sedgewick & Wayne. Colours are relative to the problem: O(n log n) is fair for a sort but bad for a single lookup. Type in the search box to filter every table at once.
Sort visualiser animates eleven sorts — bubble, insertion, selection, Shell, quicksort with a naive or median-of-three pivot, mergesort, heapsort, a simplified Timsort, counting, and LSD radix — on random, nearly sorted, reversed, or few-unique data, with play, pause, single-step, speed, and size controls. Comparisons flash yellow, swaps red, and writes orange; the counters show how the totals compare with n log₂ n and n². Try quicksort with the naive pivot on reversed data to see its O(n²) worst case, then switch to median-of-three. ▶ Visualise in the cheat sheet jumps straight to an algorithm.
Fibonacci calls draws the call tree of the naive recursive fib(n) for n from 0 to 12, one
node per call, coloured by its argument, so repeated colours are repeated work (fib(5) computes
fib(2) three times and fib(3) twice). Tick Memoise and the tree collapses into a single path
with short side-branches: a call whose answer is already cached is a small grey leaf that does no
work. Animate calls and Step show the calls in the order they happen (depth first). The
readout puts the call count beside 2F(n+1) − 1 (naive) and n + 1 (distinct values), and a table
carries the race on to n = 40: 242,785 naive calls for n = 25 against 26 computations.
Recursion trees unrolls a divide-and-conquer recurrence level by level, with T(1) = 0: merge sort T(n) = 2T(n/2) + n, binary search T(n) = T(n/2) + 1, and visiting every node of a balanced tree T(n) = 2T(n/2) + 1. Each row is one level, its sub-problems drawn with width proportional to size, and the work done on that level at the right. Merge sort does n work on each of log₂ n levels, so T(n) = n log₂ n exactly when n is a power of 2 (T(16) = 64, T(1024) = 10,240). Other n split into ⌈n/2⌉ and ⌊n/2⌋; very large n (up to 10⁹) are drawn as "pieces × size" per level.
Halving is binary search on a sorted array of n items, n from 1 to 10¹² (type it, 1e9 works,
or use the slider). The top strip is the whole array with the target in red; each row below is
the range before one comparison, split at its middle, with the kept half coloured. Search
animates it; Step goes one comparison at a time. Beside it are the comparisons used, log₂ n,
⌈log₂ n⌉, the bits needed for n (⌊log₂ n⌋ + 1, computed exactly, not with floating-point logs),
and the height ⌊log₂ n⌋ of a balanced tree holding n keys: all "how many times can you halve
n?", give or take one. Below: the in-your-head estimate (write n ≈ m × 1000ʲ, then log₂ n ≈
10j + log₂ m, so 64 million ≈ 26) and the height log_B n of a B-tree with branching factor B.
Amortised append appends n items to a dynamic array that starts with a given capacity and,
when full, either grows by a factor g (×2 like Java’s ArrayList, ×1.5 like many C++ libraries,
×1.125 like CPython; the new capacity is ⌈g × capacity⌉, at least one more) or by a constant
number of slots. Every element written counts, copies included. The bars are the cost of each
append, with the spikes at resizes and the running average; the accounting view charges each
append a fixed number of tokens (3 for doubling, 1 + g/(g − 1) in general, 3 for a constant
increment) and plots what is left in the bank. With geometric growth it never goes negative;
with a constant increment it soon does, because the copying is quadratic. The table repeats the
book’s run for n = 10, 1,000 and 1,000,000 under the current rule (25, 2,023 and 2,048,575
writes with doubling). Up to 10⁷ appends are counted; the charts show the first 2,000.
Attention & KV cache is the same arithmetic applied to language models. Attention vs SSM plots the work per layer over a context of N tokens: self-attention scores every pair of tokens (N²), a state-space model such as Mamba updates a fixed-size state once per token (N); the table shows what doubling the context does (×4 against ×2). KV cache: cumulative work counts the work of generating N tokens one at a time, where step i sees i tokens. Without a cache every step recomputes the keys and values of all earlier tokens: 1 + 2 + … + N = N(N+1)/2 projections, O(N²), and recomputing the whole causal attention each step adds up to N(N+1)(N+2)/6, O(N³). With a cache each step projects one new token, N in all, O(N), but still scores its query against every cached key, so attention stays Σ i = O(N²) — the cache removes the recomputation, not attention’s quadratic cost. Both charts are log-log.
Revision is for interview preparation, in five parts (pick one at the top):
-
Complexity quiz (
quiz) shows one of 58 short pieces of JavaScript, Python, Java or pseudo-code and asks for its time and its extra space, each from four choices — the wrong options include the usual mistake for that snippet. Space means memory beyond the input; the call stack counts, the output only when the snippet builds it. After both answers comes the explanation. The snippets cover plain and nested loops, doubling and halving loops, loops that look quadratic but are not (a geometric inner loop, the harmonic series, a pointer that never resets), recursion (Fibonacci with and without memoisation, merge sort, binary search, halving recursions, permutations and subsets), amortised costs (dynamic-array appends, a queue from two stacks, a monotonic stack, union-find) and traps such as string concatenation in a loop,inon a list, slicing inside recursion andshift()in a loop. Pick a topic to practise just one kind. -
Operation costs (
drill) asks the average or worst-case cost of one operation at a time on a dynamic array, singly and doubly linked lists, a hash map, a binary heap, an unbalanced and a balanced binary search tree, a trie, union-find with path compression and union by rank, and a graph stored as adjacency lists or as a matrix. The answers agree with the cheat sheet; the whole table is underneath. -
Master theorem (
master) solves T(n) = a·T(n/b) + f(n) for f(n) = Θ(nᵏ logᵖ n): it compares f(n) with n^(log_b a), names the case (with the extended second case for log factors, and the regularity condition in case 3) and gives the result. A recursion tree shows six levels — the number of sub-problems on each and the level’s total work relative to the root — so you can see the work grow towards the leaves (case 1), stay level (case 2) or shrink below the root (case 3). It says when the theorem does not apply (a < 1, b ≤ 1). -
Recurrences (
recs) lists sixteen that come up again and again — binary search, merge sort, Karatsuba, Strassen, Towers of Hanoi, naive Fibonacci, quicksort’s worst and average case, T(n) = T(√n) + 1 and others — with the solution and the method; Solve ▸ opens those of the master-theorem form in the solver. -
Score (
score) counts right answers in the quiz and the drill, your current and best streak, and accuracy by topic with the weakest first. It is kept in this browser; Reset score clears it.
Limits
-
The call tree is drawn up to n = 12 (465 calls); the counts table goes further with formulas.
-
The recursion tree draws individual sub-problems when a level has at most 64 of them.
-
Halving takes n up to 10¹² (JavaScript numbers are exact integers there).
-
Amortised append counts up to 10⁷ appends, growth factors from 1.01 to 4.
-
Attention & KV cache counts operations up to a constant factor (head dimension, heads, layers) for N up to 10⁷ tokens; it is the shape of the growth, not a timing.
-
The master-theorem solver takes polynomial-times-log driving functions only, f(n) = nᵏ logᵖ n; the recursion-tree picture shows the first six levels.
Related: graphing (plot your own growth functions), floating point, boolean logic, AI hardware calculator (the KV cache in bytes), softmax and attention.
Companion to Sequences and series: computer science and Exponentials and logarithms: logarithms in computer science of Mathematics, Reconnected; the growth races also follow Powers: a first look at exponential growth and why exponentials beat polynomials.
The Attention & KV cache tab is a companion to AI Acceleration: From Transistors to Trillion-Parameter Models: why the KV cache’s savings compound (Part III) and beyond the transformer: state-space models (Part XVIII).
Sharing
Share link copies a URL that opens this tool exactly as you have it. Hand-written links work too: Each tab shares its own settings: Growth curves ?classes=n,nlogn,n2&n=1000&log=1, Time & budget ?ops=&budget=&sizes=, Cheat sheet ?q=heap, Sort visualiser ?algo=merge&data=reversed&size=80. A shared benchmark fills in the code but only runs when you press Run benchmark. For example ?algo=heap&data=nearly&size=100#vis.
Linking to an example
Every tab can be opened from a link written by hand. Put the tab after : growth, time,
bench, ref, vis, fib, tree, halve, amort, seq or rev. Without a , the tab that owns the
parameters opens. Numbers may be written 1e9, 64e6 or 1_000_000.
| Parameter | Meaning | Example |
|---|---|---|
|
one of the book’s examples, below; parameters written beside it override it |
|
|
growth curves shown: |
|
|
growth: largest n; fib: the call fib(n), 0–12; tree: problem size; halve: array size, 1–10¹²; amort: number of appends; seq: tokens N, 2–10⁷ |
|
|
growth axes: |
|
|
growth race: the power in nᵏ (1–10) and the base of bⁿ (1.001–3) |
|
|
time & budget: operations per second, budget in seconds, sizes to time |
|
|
benchmark: code, size range, number of sizes, |
|
|
cheat sheet search |
|
|
sort visualiser: algorithm, |
|
|
fib: |
|
|
tree: |
|
|
halve: target position as a fraction of n, 0–1 |
|
|
halve: B-tree branching factor |
|
|
amort: growth factor |
|
|
amort: grow by this many slots instead (a constant increment) |
|
|
amort: starting capacity |
|
|
seq: |
|
|
revision: the part to open — |
|
|
revision, master theorem: a, b, and f(n) = n^mk log^mp n in T(n) = a·T(n/b) + f(n) |
|
For example ?n=8&memo=1#fib or
?algo=heap&data=nearly&size=100#vis.
Examples from Mathematics, Reconnected (?example=…):
| Name | Shows |
|---|---|
|
n to n! on a log axis (chapter 3’s growth race) |
|
the largest n each class handles at 10⁹ steps per second in a second, an hour, a year |
|
log n, n, n log n, n³ and 1.01ⁿ to n = 4000 on a log y-axis: 1.01ⁿ overtakes n³ near 2,340 |
|
the same race on log-log axes |
|
the halving explorer on a million items |
|
a billion items: 30 comparisons |
|
log₂ of 64 million in your head: 26 (exact 25.93) |
|
a B-tree with B = 500 holds a billion keys in about 3.3 levels |
|
merge sort on 64 items: log₂ n levels of n work |
|
1,000 appends with doubling: 2,023 writes |
|
10 appends: 25 writes |
|
growing by a fixed 100 slots: quadratic copying |
|
growth factor 1.5 |
|
T(n) = 2T(n/2) + n for n = 16: 64 = 16 log₂ 16 |
|
T(n) = T(n/2) + 1 unrolls to log₂ n |
|
T(n) = 2T(n/2) + 1 sums a geometric series to n − 1 |
|
the call tree of naive fib(5), as in the book’s figure |
|
naive fib(10): 177 calls |
|
memoised fib(10): a single path with short side-branches |
Examples from AI Acceleration (?example=…):
| Name | Shows |
|---|---|
|
attention’s N² against an SSM’s N up to 128K tokens: doubling the context is ×4 against ×2 (open) |
|
O(N²) and O(N) to a million on the growth chart, log-log (open) |
|
generating 5,000 tokens: 12,502,500 K/V projections without a cache, 5,000 with one; attention 2.1 × 10¹⁰ against 1.25 × 10⁷ (open) |
|
50 tokens: 1,275 projections against 50 (open) |
Revision examples (?example=…):
| Name | Shows |
|---|---|
|
the complexity quiz on code snippets (open) |
|
the drill on data-structure operation costs (open) |
|
merge sort, T(n) = 2T(n/2) + n: case 2, Θ(n log n) (open) |
|
Karatsuba, T(n) = 3T(n/2) + n: case 1, Θ(n^(log₂ 3)) ≈ Θ(n^1.585) (open) |
|
Strassen, T(n) = 7T(n/2) + n²: case 1, Θ(n^(log₂ 7)) ≈ Θ(n^2.807) (open) |
|
T(n) = 2T(n/2) + n²: case 3, the root dominates, Θ(n²) (open) |
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.