johnsoncodehk
## Background SH3-5 round 1 (`&'static str` typ/keys + move semantics, b82f1a9) brought the typescript-shape ast/cst ratio from **22.6x down to 10.2x** (2MB input, 32/32 gates passing). This issue records the round-2 profiling results and remaining work. ## Profiling setup - Binary: `/tmp/shape-rust-gate/profile-loop2` (typescript-shape.rs + loop main, `rustc -O`) - Input: `/tmp/shape-rust-gate/typescript-bench-2mb.ts` (2MB) - Tool: macOS `sample` for 8s, report at `/tmp/sh35-round2.sample.txt` ## Hotspots (excluding main-thread join wait and startup samples) Roughly **60% of work time is still in malloc/free** (malloc_tiny 733 + free 686 + memmove/memset samples). Sources by contribution: ### 1. `shape_restore` (384) + `drop_in_place<AstValue>` (274) On backtracking, `kids.truncate()` recursively drops already-built subtrees; and every checkpoint via `shape_ck()` `clone()`s both suppress vectors (`src/target-rust.ts` L4340–4348), with restore doing whole-Vec assignment again. **Fix (O3)**: if the suppress vectors are append-only, store only their lengths and restore via truncate, saving two Vec clones + two drops per checkpoint. Apply the same change to `shape_tpl_snap`/`shape_tpl_restore` (L4326–4338). ### 2. `AstValue::clone` (126) + `Vec::clone` (68) — fixture customs The codegen side is fully cleaned up; all remaining deep copies live in `test/fixtures/shape-typescript-rust-customs.rs` (~900 lines): - `ctx.kids.get(N).cloned()` throughout the `estree_*` functions (deep subtree copies) - `first_kid` / `flat_kids` borrow then clone - `fields.iter().find(...).map(|(_,v)| v.clone())` (ForIn/ForOf/For destructuring) **Fix**: the `ast_custom` dispatch already owns `ctx` by value; change the `estree_*` functions to take `&mut AstCustomCtx` (or by value) and extract kids via `mem::replace`/`mem::take`, driving `AstValue::clone` to zero. ### 3. Wasted construction on backtracking (architectural, deferred) `parse_ast_Decl`/`parse_ast_Stmt` self-samples are non-trivial; part of it is AST built inside failing alts then discarded by truncate. Possible direction: probe-first fast path before construction. Lower ROI than items 1–2, so deferred. ## Execution order - [ ] O3: length-based snapshots for ShapeCk/TplSnap suppress vectors (small change, targets hotspot 1) - [ ] De-clone fixture customs (larger change, targets hotspot 2) - [ ] Re-bench + re-sample, then decide whether to attack hotspot 3 ## Acceptance - `node --experimental-strip-types test/shape-rust.ts` passes 32/32 - Median ast/cst on the 2MB paired timing is clearly below 10.2x