Intuition The one idea behind all of profiling
A running program spends its life doing exactly three things — thinking (CPU), remembering (memory), and waiting (I/O) — and you cannot make it faster until you measure which of the three is eating your time. Every symbol below exists only to answer one question: "where did the time actually go?"
Before you can read the parent note, you need to genuinely understand a small pile of words and squiggles it throws at you: fractions like p , a speedup S , the difference between a stopwatch on the wall and a stopwatch on the brain , a square root that measures uncertainty, and pictures called flame graphs. We build each one from nothing.
Everything starts here. Imagine time flowing left to right. A program runs along this line. At each instant it is doing one of: computing, or waiting for something.
Intuition What the picture shows
The whole bar is the total time the program took. Black chunks = the CPU is busy. The red chunk = the program is stuck waiting (for a disk, a network reply, a lock). Notice: during the red chunk the CPU does nothing , yet the clock keeps ticking. That single observation is the seed of the entire topic.
The parent note's "most important distinction" is between two ways of measuring time. You must feel the difference before any formula.
Definition Wall-clock time vs CPU time
Wall-clock time T wall — the time a clock on your wall would measure from start to finish. Also called elapsed or real time. It counts everything, including waiting.
CPU time T CPU — the time the processor was actively working on your program. Waiting does not count.
Wait time T wait — the time the program was stuck doing nothing useful on the CPU : waiting for a disk read, a network reply, a lock, or a sleep. This is the red chunk in figure s01.
The picture: look back at figure s01. The full width is T wall . Add up only the black chunks and you get T CPU . The red waiting chunk is T wait — exactly the gap between the two.
Recall
If wall time is 10 s but CPU time is 1 s, what was the program doing for 9 s? ::: Waiting — that 9 s is T wait (I/O, a lock, or sleeping); it is I/O-bound.
Definition Splitting CPU time: user vs sys
The processor's busy time itself divides into two parts, written with a superscript in parentheses:
==T CPU ( user ) == — time the CPU spent running your own code ("user space").
==T CPU ( sys ) == — time the CPU spent running the operating system on your behalf ("system space"): opening files, sending network packets, allocating memory.
They simply add back up to the CPU total:
T CPU = T CPU ( user ) + T CPU ( sys )
This is why the Unix command time ./prog prints three numbers — real (T wall ), user (T CPU ( user ) ), and sys (T CPU ( sys ) ).
Profiling constantly says things like "this function is 75% of the time". A fraction is just a part-of-a-whole written as a number between 0 and 1 .
Definition Fraction of total time,
p
Pick a whole to measure against, then p is the slice one part occupies out of that whole.
p = total time (the chosen whole) time in this part
If a function takes 30 ms and the total is 100 ms, then p = 30/100 = 0.30 (i.e. 30%).
The symbol ==p == always means "the slice of the chosen whole that this part occupies."
Common mistake Which "whole" is
p measured against?
The trap: p is meaningless until you say whole of what — wall-clock time or CPU time?
A CPU profiler measures fractions of T CPU (the busy time only). A function at p = 0.75 there means "75% of the computing time", and says nothing about waiting.
Amdahl's Law and wall-clock reasoning measure fractions of T wall (including waits). A part at p = 0.75 there means "75% of the elapsed time the user actually feels".
Fix: always name the denominator. In this note, whenever we do Amdahl-style speedup reasoning, p is a fraction of wall-clock time T wall (that is the time a user experiences and wants reduced). When we read a CPU profiler's percentages, p is a fraction of T CPU .
The picture: cut the timeline bar into slices. p is the width of one slice as a fraction of the full bar.
Intuition Why the topic obsesses over
p
Because a big p is the only thing worth optimizing. A slice with p = 0.05 can never save you more than 5% no matter how clever you are. Profiling exists to find the fat slice .
Two closely-named symbols. Keep them straight:
The picture: if the old bar was 100 ms wide and the new bar is 50 ms wide, the new bar is half as long, so S = 100/50 = 2 .
s and S
You optimize a part by s = 4 but the whole program only speeds up by S = 1.3 . Why: the part you sped up was only a small slice (p small), so shrinking it barely moves the total. This gap between s and S is exactly what Amdahl's Law measures — see Amdahl's Law .
Amdahl's derivation writes T = ( 1 − p ) + p . This is not scary — it is just "the whole = the part you touch + the part you don't."
The bracket-with-word-underneath notation label is just an arrow saying "this chunk means this." Nothing more.
Sampling profilers do not know the true p ; they estimate it by taking random snapshots. Statisticians put a hat on a symbol to mean "our estimate of, not the true value".
p ^ — the estimated fraction
==p ^ == (read "p-hat") is your guess of p built from N random samples: if 250 of 1000 snapshots caught a function running, p ^ = 250/1000 = 0.25 .
Now — why the square root? Because a guess from random samples has wobble , and the amount of wobble is what the square-root formula measures.
Definition Standard error,
S E
==S E == is the typical size of the wobble between your estimate p ^ and the truth p . Small S E = trustworthy estimate.
Common mistake But you don't know the true
p — so what goes in the formula?
The catch: the formula above uses the true p , which is the very thing you are trying to measure. Fix: in practice you substitute your estimate p ^ for p (this is called the plug-in estimate):
S E ( p ^ ) ≈ N p ^ ( 1 − p ^ )
The ≈ (not = ) is honest bookkeeping: you are estimating the wobble using an estimated fraction. For the big hotspots that matter, p ^ is close to p , so the approximation is excellent.
Recall
To halve your sampling error, how many more samples do you need? ::: Four times as many (error falls as 1/ N ).
A program's functions call other functions, forming a tree . Two ways to add up a function's cost:
Definition Self vs cumulative time
Self (exclusive) time — time spent inside a function, not counting the functions it calls.
Cumulative (inclusive) time — self time plus everything its callees consumed.
The picture: a boss (parent function) who delegates. Cumulative = the whole department's hours. Self = only the boss's own hours. A boss who only forwards emails has huge cumulative time but tiny self time.
Common mistake Optimizing by cumulative time
A wrapper function shows 90% cumulative time, so you "fix" it — but its self time is 1%; the real work is in a callee. Fix: to find where cycles actually burn, sort by self time . This directly feeds how you read Flame Graphs .
Once self/cumulative time and the call tree click, a flame graph is obvious: stack the call tree as boxes, and make each box's width proportional to time . Wide box = hotspot.
This is the parent note's main visual. Everything you need to read it, you now have: a call tree (§6), and time-as-width (which is just fraction p turned into pixels, §2). Deep dive lives in Flame Graphs .
The topic splits "slow" into three buckets. You met all three in figure s01 conceptually; here are their names.
Definition CPU / Memory / I/O
CPU-bound — the processor is genuinely busy computing.
Memory-bound — too much is allocated or held alive (ties to Memory Management & Garbage Collection ).
I/O-bound — waiting on disk or network (ties to the N+1 Query Problem and Caching Strategies ).
Wall time vs CPU time vs wait time
Fraction p of a chosen whole
CPU vs Memory vs IO bound
Amdahl decides what to optimize
Hat p and square root error
Performance profiling topic
This map is a preview of the parent topic . If any box confuses you, re-read its section above.
Say the answer out loud before revealing. If you miss one, revisit its section.
I can explain wall-clock time in one sentence The time a clock on the wall measures start-to-finish, including all waiting.
I can explain CPU time and how it differs from wall time Time the processor was actively working; it excludes waiting, so it can be far less than wall time.
I know what T wait is The time the program was stuck doing nothing on the CPU — waiting for I/O, a lock, or a sleep; it is the gap T wall − T CPU .
I can split CPU time into user and sys T CPU = T CPU ( user ) + T CPU ( sys ) — my code vs the OS working for me.
I know what the symbol p means, and against what whole The fraction (0 to 1) of a chosen total a part occupies — wall-clock time for Amdahl, CPU time for a CPU profiler.
I can tell s from S s = how much faster one part got; S = how much faster the whole program got.
I can read ( 1 − p ) notation A bracket labelling a chunk — here, the fraction of time you did not optimize.
I know what the hat in p ^ means An estimate of p built from samples, not the true value.
I know what actually goes into the SE formula in practice The plug-in estimate
S E ( p ^ ) ≈ p ^ ( 1 − p ^ ) / N — you substitute
p ^ because the true
p is unknown.
I know why S E has a square root of N Random averaging error shrinks like
1/ N , so 4× the samples halves the error.
I can distinguish self time from cumulative time Self = a function's own work only; cumulative = self plus all its callees.
I know why flame-graph width means time Each box's width is drawn proportional to how long that call took.
I can name the three resource buckets CPU (busy), Memory (holding too much), I/O (waiting).