Skip to content

internal/report: count each address once per sample in weblist - #1030

Open
Hee-San wants to merge 1 commit into
google:mainfrom
Hee-San:issue-707-weblist-cum
Open

Hee-San wants to merge 1 commit into
google:mainfrom
Hee-San:issue-707-weblist-cum

Conversation

@Hee-San

@Hee-San Hee-San commented Sep 21, 2026

Copy link
Copy Markdown

Updates #707. This is the first of two PRs; the analysis is in #707 (comment).

newSourcePrinter did cum[addr] += value for every frame of every sample. With recursion the same address is on the stack many times within one sample, so the sample was added to that address once per frame. On a CPU profile of a recursive fib (total 310ms), one 10ms sample with 29 fib frames added 190ms to one call instruction and 90ms to the other.

This counts each address at most once per sample, the same way newGraph does with its seenNode set. It affects -weblist and the web UI Source page, which both go through MakeWebList.

It looks like a regression from #599 (cbba55b). Before that, weblist went through rpt.newGraph and got the deduplication for free. The README documents the rule this restores: "Samples that include a location multiple times (e.g. for recursive functions) are counted only once per location."

Effect on the fib profile:

                          before              after
weblist header            8.55s  2758.06%     900ms  290.32%
call fib(n-1)             5.20s               300ms
call fib(n-2)             3.05s               300ms

The values after the change are the ones -disasm already reports for the same profile. They are still above 100% because the header is a sum over instructions that one recursive sample contributes to more than once. That is a separate cause with a separate fix (the second PR), so this one says Updates, not Fixes.

What doesn't change: flat, which is only added for the leaf frame; weblist output for profiles without recursion, which I checked is byte-for-byte identical on testdata/sample.bin + sample.cpu; and every other view, since nothing else uses newSourcePrinter.

The test has two samples. In one the recursive call address is the leaf as well as an outer frame, which also pins down that flat is still counted when the address has already been seen. Moving the flat update inside the new if would make it fail.

newSourcePrinter accumulated cum[addr] += value for every frame of every
sample. For a recursive function the same address is on the stack many
times within one sample, so the sample was added to that address once per
frame. Count each address at most once per sample instead, the same way
newGraph does with its seenNode set. flat is only accumulated for the leaf
frame, so it is unaffected.

Updates google#707.
@Hee-San

Hee-San commented Sep 21, 2026

Copy link
Copy Markdown
Author

Screenshots of -weblist main.fib with the assembly expanded. They are from macOS, where llvm-symbolizer gives no line numbers for Go binaries, so all instructions land under one entry.
prA-before
prA-after

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant