Simon Jakobi pushed to branch wip/sjakobi/cgwork-perf-aggregate at Glasgow Haskell Compiler / GHC Commits: bbd4bce4 by Simon Jakobi at 2026-06-30T03:20:28+02:00 cgwork perf-aggregate: resolve Tc.Zonk.Type.$wgo_tys to zonk identity-rebuild The zonk mapper (mapTyCoX) rebuilds TyConApp arg-lists/nodes wholesale; in the driver T9872b_defer it is the #1 allocator (417.6 MB) yet does only 273 tyvar substitutions + 6 hole fills, so ~all of it is identity copying. Body optimal (A done); lever is a reallyUnsafePtrEquality# short-circuit, an allocation (not Ir) win. Full writeup: ~/ghc/todos/zonk-maptyco-identity-rebuild-ptr-eq.md Assisted-by: Claude Opus 4.8 - - - - - 8b55e18a by Simon Jakobi at 2026-06-30T11:49:03+02:00 cgwork perf-aggregate: resolve castCoercionKind_go to opt_trans_rule Identity rule (construction half) castCoercionKind_go/_go1 (suite #15, 1.06%) are GHC-mangled names for the coercionLKind/coercionRKind walkers. They are the type-construction half of the same opt_trans_rule Identity rule that drives eq_type_expand_ignore (#2): they freshly materialise ty1/ty2 for its eqType. Top driver is T13386 (not T8095), which inverts the comparison-dominated case: building coercionLKind co1 = 27.1M node-ops vs the eqType walk's 1.0M (shallow reject, reflexive 0.45% of calls). A comparison-only fix would miss this; folded into the existing todo. Assisted-by: Claude Opus 4.8 - - - - - 8fcddb84 by Simon Jakobi at 2026-06-30T12:27:13+02:00 cgwork perf-aggregate: resolve elems1 11.2 GB to RoughMap.lookupRM' unifier fold The InstanceMatching1 elems1 cost is the unifier enumeration in lookupRM' (via matchInstEnv/tcExtendLocalInstEnv1 on variable-headed goals): foldDNameEnv = foldUDFM = sortBy . M.elems sorts+materialises all instances to answer a zero/non-zero question, defeating the laziness Note [Matches vs Unifiers] relies on. Full mechanism, caller chain, lever, and order-independence caveat in roughmap-lookuprm-elems-materialization.md (~/ghc/todos). Assisted-by: Claude Opus 4.8 - - - - - 1 changed file: - FINDINGS.md Changes: ===================================== FINDINGS.md ===================================== @@ -146,6 +146,33 @@ deliverable. Investigation + (B) levers (guard the optional check / share endpoint types / reshape chain optimisation): [[opt-trans-rule-identity-eqtype-deep-walk]] in `~/ghc/todos`. +- **`castCoercionKind_go` (suite #15, 1.06 %) is the *construction half* of that + same Identity rule** — not an independent opportunity. The mangled name hides two + coercion-kind walkers: `castCoercionKind_go` = `coercionLKind`, `castCoercionKind_go1` + = `coercionRKind` (the two inlined `coercion_lr_kind` copies). They **freshly + materialise** the `ty1`/`ty2` that the rule's `eqType` then compares, so the + earlier "no allocation" note undercounts the rule. **Driver is T13386** (95 % + `$wopt_trans_rule`), and it *inverts* T8095: building `coercionLKind co1` = 27.1 M + node-ops vs. the `eqType` walk's 1.0 M (shallow reject, reflexive 0.45 % of calls) + — we build a deep type ~27x larger than the comparison needs, then reject it after + ~4 nodes. So the rule's true cost = construction (#15) **+** comparison (#2); a + comparison-only fix misses T13386. Folded into + [[opt-trans-rule-identity-eqtype-deep-walk]] (construction-half section). + +### Zonk type/coercion mapper (`Tc.Zonk.Type` `mapTyCoX`) + +- **`$wgo_tys` (suite #13, 1.14 %) is resolved**: it is the `[Type]` arm of + `mapTyCoX` (the zonker's map). Driver **T9872b_defer** (67 % of entries), where + `$wgo_tys` is the **#1 allocator in the whole test**: 22.3M entries / **417.6 MB**. + The decisive ratio: across ~45M visited type/coercion nodes the mapper does only + **273** tyvar substitutions and **6** coercion-hole fills — so essentially the + entire alloc is the zonker **re-allocating `TyConApp` arg-lists/nodes structurally + identical to their inputs**. Caller chain `go_tys ← go_ty(TyConApp) ← go_co`, i.e. + driven by zonking the huge coercions in deferred-error evidence. Body already + optimal (A done); lever is a `reallyUnsafePtrEquality#` identity short-circuit in + the shared mapper — an **allocation** win (GC/bytes-allocated), Ir-neutral, and it + also covers `Tc.Zonk.TcType`'s zonker. Investigation + lever: + [[zonk-maptyco-identity-rebuild-ptr-eq]] in `~/ghc/todos`. ### Interface load/write (MultiLayerModules) @@ -165,6 +192,7 @@ deliverable. | `Word64Map.$winsert` (#6) | ManyConstructors | | `coVarsOfType(s)` | T16577 | | `Core.Map.Type` / de Bruijn eq | T9872b | +| `Tc.Zonk.Type.$wgo_tys`/`go_ty` (zonk mapper) | **T9872b_defer** (67 % of `go_tys` entries) | | iface (utf8/alex/ULEB, GenUnit==) | MultiLayerModules | ## Ticky phase — source-level entry counts + an allocation axis @@ -206,7 +234,14 @@ lot". Ticky separates them, and they point at *different* functions: deterministic `UniqDFM` fold materialises its element list (`foldr (:) []`) *and* sorts it by insertion tag. This single list-materialisation is the largest cost source in the whole investigation — invisible to Ir (cons is Ir-cheap), enormous - in bytes. Lever (B): avoid materialising/ordering these solver-map folds. + in bytes. The driver is **`RoughMap.lookupRM'`'s *unifier* enumeration** (99.9 %, + via `matchInstEnv`/`tcExtendLocalInstEnv1` solving variable-headed `Show a` goals): + `foldDNameEnv`=`foldUDFM`=`sortBy . M.elems` sorts+materialises all 10,000 `Show` + instances just to answer the zero/non-zero unifier question, defeating the laziness + `Note [Matches vs Unifiers]` relies on. Lever (B): non-deterministic unifier fold + (order matters only for error messages). Mechanism, caller chain, lever, and the + order-independence caveat written up in + [[roughmap-lookuprm-elems-materialization]] in `~/ghc/todos`. - **T8095 = the `eq_type_expand_ignore` driver** (187.1M entries, **0 B**), entered via `eqTypeIgnoringMultiplicity` only 251k times → ~745 recursive node-compares per top-level type comparison. Pure volume; body already has the View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/fd9f3eeff1b8ad28223088d949e440f... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/fd9f3eeff1b8ad28223088d949e440f... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Simon Jakobi (@sjakobi2)