mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 19:33:42 +00:00
IC: make timed arm the profiler, and price the C compiler
`timed` recorded into `profNanos` but never called `armProf()`, so a
process whose only instrumentation is a `timed` never registered the exit
dump and reported nothing at all. The `merge`, `emit` and `link` stages
have been silently absent from every profile in this branch — including
the one I used to claim the backend was fully accounted for.
With them present, Atlas cold at batch size 16, parallel (9.66s elapsed):
frontend 181 proc 10.60 s summed process wall
lower 14 proc 4.49 s
cg 14 proc 4.50 s
merge 1 proc 0.20 s
emit 14 proc 0.42 s
link 1 proc 1.65 s <- the entire C compile + link
That settles the C compiler as a target: its 12.2s of CPU is 1.65s of
wall, because `callCCompiler` fans out across cores, and the excess over
a whole-program build is ~0.4s of it. `bnode.nim` records where the
excess is — 3.8MB of the 5.4MB is per-TU prototypes and typedefs, which
is intrinsic to emitting 204 translation units instead of 139 — and why
the obvious sub-target is not one either: 53 of the 204 object files
define nothing, and compiling all 53 costs 0.23s of user time.
Fewer, larger TUs is the only real fix, and it trades directly against
what IC is for: a sandwich edit rebuilds exactly one `.c` and one `.o`.
Behind `-d:icBNodeProf`. ic 42/42.
This commit is contained in:
@@ -163,6 +163,33 @@
|
||||
## and build into a LOCAL table before assigning it back (loading symbols can
|
||||
## grow `g.ifaces`, which would leave a `var` alias into it dangling).
|
||||
## `tests/ic/timporthidden.nim` is what says all of this still holds.
|
||||
##
|
||||
## THE C COMPILER is the largest CPU item of a cold Atlas build and the smallest
|
||||
## wall lever, which is worth writing down so nobody spends a week on it. gcc is
|
||||
## 12.2s of CPU against a whole-program build's 10.2s — but `callCCompiler`
|
||||
## fans out across cores, so the whole `link` stage is 1.65s of the parallel
|
||||
## build's 9.66s, and the EXCESS over a whole-program build is ~0.4s of wall.
|
||||
##
|
||||
## Where the excess is, measured on Atlas (204 IC TUs / 20.85MB against
|
||||
## non-IC's 139 / 15.47MB):
|
||||
##
|
||||
## function definitions 3097 vs 3471 (IC emits FEWER; `merge` dedups,
|
||||
## and 0 duplicated definitions)
|
||||
## prototypes 11782 vs 7185 +64%
|
||||
## typedefs (instances) 5870 vs 4854
|
||||
## declaration bytes 8.14MB (39%) vs 4.37MB (28%)
|
||||
## body bytes 12.71MB vs 11.10MB
|
||||
##
|
||||
## So 3.8MB of the 5.4MB excess is per-TU DECLARATIONS — prototypes and
|
||||
## typedefs each TU needs for what it references. That is intrinsic to having
|
||||
## 204 translation units instead of 139, and the only real fix is fewer, larger
|
||||
## TUs, which trades directly against the thing IC exists for: a sandwich edit
|
||||
## currently rebuilds exactly one `.c` and one `.o`.
|
||||
##
|
||||
## The tempting sub-target is a dead end too: 76 of the 204 TUs contain no
|
||||
## function definition at all and 53 produce object files that define NOTHING,
|
||||
## but compiling all 53 costs 0.23s of user time. Skipping them is worth ~5% of
|
||||
## the C compile and nothing measurable in wall.
|
||||
## * `-d:icBridgeOnly` builds the buffer but generates off the tree, which
|
||||
## separates the ENCODER's cost from the READER's. Encoding is free — it does
|
||||
## not show in wall time at all.
|
||||
|
||||
@@ -96,6 +96,11 @@ when defined(icBNodeProf):
|
||||
## Leaf timing. NOT re-entrant, and the phase slots are not disjoint —
|
||||
## `tTransform` contains body materialization, `tTyp` reaches `tSym`. Read
|
||||
## them as nested, not additive.
|
||||
##
|
||||
## Arms the dump like `prof`/`icProfStart` do. It did not, and so a process
|
||||
## whose ONLY instrumentation is a `timed` never reported at all: the
|
||||
## `merge`, `emit` and `link` stages were silently absent from every profile.
|
||||
armProf()
|
||||
let t0 = getMonoTime()
|
||||
body
|
||||
profNanos[s] += (getMonoTime() - t0).inNanoseconds
|
||||
|
||||
Reference in New Issue
Block a user