← Back · anthropic-design diagram gallery← 返回 · anthropic-design 图示案例库 performance · two figures that argue性能 · 两张会讲道理的图

Two figures
that change what
you go and fix.
两张图,
会改变你接下来
去修哪儿。

Most performance figures report. These two argue. One puts a unit on the horizontal axis so a box stops being a name and starts being a share of the cost. The other puts the wait against utilisation, which is the one relationship people reliably get wrong, because the axis is linear and the experience is not.大多数性能图是在汇报。这两张在讲道理。一张给横轴加上单位,于是一个方块不再只是个名字,而是一份开销占比。另一张把等待画在利用率上——这是人们最容易搞错的一条关系,因为轴是线性的,体验不是。

28%the widest plateau, and the thing to fix最宽的那个平顶,也就是该修的那个
the wait at 80% busy, against 50%80% 忙时的等待,相对 50%
19×the wait at 95% busy95% 忙时的等待
what is measured and what is illustrative哪些是实测,哪些是示意

Nothing on this page is a measurement. The profile percentages were chosen so the arithmetic adds up, and the queue curve is the textbook shape for one server with random arrivals. Both figures say so on their own faces, because a figure that looks like data and is not is worse than one that never pretended. What is real is the shape of both relationships, and the shape is what these two figures exist to argue about.这一页上没有一个数字是实测的。采样占比是挑出来让算术对得上的,队列曲线是单服务台、随机到达那个教科书形状。两张图自己都写明了这一点——因为一张长得像数据、其实不是的图,比一张从不假装的图更糟。真实的是两条关系的形状,而这两张图存在的理由就是为那个形状讲道理。

A box has two dimensions and most diagrams spend one.一个方块有两个维度,大多数图只花掉一个。

In an ordinary call graph, a box is as wide as its name happens to be. That is a whole dimension carrying nothing, and filling it costs nothing: let width be share of samples and the same six functions stop being a structure and become a budget. The figure shows both drawings side by side because the difference is easier to accept than to describe — the left one is not wrong, it simply answers “who calls whom” and was never going to answer “where did the time go”.在普通的调用关系图里,一个方块的宽度由它名字的长度决定。那是一整个维度什么都没承载,而把它填上不花任何代价:让宽度等于采样占比,同样这六个函数就从一个结构变成了一本账。这张图把两种画法并排放,是因为这个差别更容易被接受而不是被描述——左边那张并没有错,它答的是「谁调用谁」,本来就不打算答「时间去哪儿了」。

WIDTH WITH A UNIT · THE SAME PROFILE, DRAWN TWICE a box has two dimensions and most diagrams spend only one of them. here the horizontal one is doing work: it is the share of the profile that frame accounted for. AS A CALL GRAPH · WIDTH MEANS NOTHING main handle_request background_flush parse_json db_query render memcpy net_recv write every box is as wide as its name happens to be. that dimension is empty. it costs nothing to fill. the graph is not wrong — it answers “who calls whom”. it just cannot answer “where did the time go”. AS A FLAME GRAPH · WIDTH IS SHARE OF SAMPLES main 100% handle_request 78% background_flush 22% parse_json 31% db_query 34% render 13% write 19% memcpy 12% net_recv 28% the widest plateau, not the tallest tower 0% 50% 100% share of samples — not elapsed time application code library kernel the one worth acting on the horizontal axis is share of samples, so neighbouring boxes are not sequential. two boxes side by side did not run one after the other — they are sorted by name, which keeps the shape stable between runs. reading a flame graph left to right as a timeline is the single most common way to misread one. the vertical axis is stack depth, not duration. a tall thin tower is a deep call chain that cost almost nothing, and it is exactly what the eye is drawn to first. a profile with no wide plateau is telling you the cost is spread thin. colour here groups frames by where the code lives. random colour is the usual convention for this figure type, and it spends a whole dimension on nothing. the percentages are an illustrative profile, chosen so the arithmetic adds up. the shape is the lesson, not the numbers. Flame graph · width has a unit
width with a unit宽度带上单位 Colour here groups frames by where the code lives rather than being random. Random colour is the usual convention for this figure type and it spends an entire dimension on nothing — which is the same mistake the call graph makes with width, one axis over.这里的颜色按代码归属分组,而不是随机的。随机配色是这类图的常见做法,它把一整个维度花在了零信息上——跟左边那张调用图对宽度犯的错,是同一个错,只是换了一个轴。
reading it left to right as a timeline把它从左往右当时间线读
The most common way to misread one. The horizontal axis is share of samples; neighbouring boxes are sorted by name, not by when they ran, and that sorting is what keeps the shape stable between runs so two profiles can be compared at all.这是第一号误读。横轴是采样占比;相邻的方块按名字排序,不是按运行先后——而正是这个排序让形状在多次采集之间保持稳定,两份采样才有得比。
chasing the tallest tower去追最高的那座塔
The vertical axis is stack depth, not duration. A tall thin tower is a deep call chain that cost almost nothing, and it is exactly what the eye goes to first. The target is the widest plateau.纵轴是栈深,不是时长。又高又细的塔是一条几乎不花时间的深调用链,而它恰恰是眼睛最先去的地方。要找的是最宽的那个平顶。
a profile with no wide plateau一份没有宽平顶的采样
Not a broken profile. It is telling you the cost is spread thin and there is no single thing to fix — which is a real answer, and a much more useful one than an hour spent looking for the bar that is not there.这不是采样坏了。它在说开销摊得很平,没有单独一件事可修——这是一个真的答案,而且比花一小时去找一根根本不存在的柱子有用得多。

The last twenty per cent of load is not twenty per cent of the trouble.最后那 20% 的负载,不是 20% 的麻烦。

Show somebody three queues at three loads and they will read a proportion: busier means proportionally slower. The real relationship bends. Going from half busy to eighty per cent busy costs four times the wait; going from eighty to ninety-five costs another five times on top of that. This is the single most reliable gap between what a utilisation number feels like and what it does, and a picture of queues cannot close it on its own — only the curve underneath can.给人看三个负载下的三条队列,他读到的是一个比例:忙一点就按比例慢一点。真实的关系是弯的。从半忙到八成忙,等待变四倍;从八成到九成五,在此之上再乘五倍。这是「一个利用率数字给人的感觉」和「它实际造成的后果」之间最稳定的一道落差,而光画队列关不上这道落差——只有底下那条曲线能。

A QUEUE IS NOT A PROPORTION · THE LAST 20% OF LOAD IS NOT 20% OF THE TROUBLE the three panels are the same server at three loads. the curve underneath is why the third one looks the way it does, and it is the part a queue drawing usually leaves out. 50% busy half the time it is idle server one at a time arrivals 1 waiting the queue empties between arrivals 80% busy the usual production target server one at a time arrivals 4 waiting four waiting, and it feels fine on a graph 95% busy “we still have headroom” server one at a time +10 arrivals 19 waiting nineteen waiting. nothing broke — it just queued AVERAGE WAIT AGAINST UTILISATION · ONE SERVER, RANDOM ARRIVALS 0% 20% 40% 60% 80% 100% 10× 15× 20× wait the knee 1× at 50% 4× at 80% 9× at 90% 19× at 95% going from 50% to 80% busy costs four times the wait. going from 80% to 95% costs another five times on top of that. the axis is linear; the experience is not. this shape is one server with random arrivals. a real system with bursty arrivals bends earlier and harder, so treat the curve as the floor of the bad news rather than the estimate. the three panels above cannot make this point on their own — a reader who sees only queues believes a busy system is a proportionally slower one. the curve is what says otherwise. the same shape governs an interrupt handler, a ring buffer and a thread pool. what changes between them is what happens after the queue is full, not the shape of the approach. Queue pressure · the knee
the knee, drawn把那个膝点画出来 The three panels above the curve are the entry point, not the argument. Nineteen items waiting at ninety-five per cent is the same fact as nineteen times the wait, drawn as something you can count. Below eighty per cent the curve is unremarkable, which is exactly why the number feels safe right up until it does not.曲线上面那三格是入口,不是论证。95% 时有十九个在排队,跟等待变十九倍是同一个事实,只是画成了能数得出来的东西。80% 以下这条曲线平平无奇——而这正是为什么那个数字一直让人觉得安全,直到它不再安全。
what this shape assumes这条形状的前提

One server, random arrivals — so treat it as the floor单服务台、随机到达 —— 所以把它当下限

A real system has bursts, and bursts bend the curve earlier and harder. So the honest way to use this figure is as the best case: whatever it says the wait will be at a given load, the machine in front of you will be worse. That is also why a target of eighty per cent utilisation is a decision about how much bad news you are willing to buy, not a safety margin.真实系统有突发,而突发让这条曲线弯得更早、更狠。所以老实的用法是把它当最好情况:它说某个负载下等待是多少,你面前那台机器只会更差。这也是为什么「利用率目标 80%」是一个「你愿意买多少坏消息」的决定,而不是一条安全余量。