Summary#
Profile memory usage across all subsystems and optimize the most impactful allocations. This is the final issue in Phase 15, meant to be tackled after other optimizations are in place.
Background#
A browser engine allocates heavily: DOM nodes, layout boxes, style data, JS heap objects, display lists, glyph atlases, connection buffers. This issue is about measuring where memory goes and reducing waste through targeted optimizations.
Acceptance Criteria#
- Memory accounting: add lightweight allocation tracking to major subsystems:
- DOM tree (node count, estimated bytes)
- Layout tree (box count, estimated bytes)
- Style data (computed style count, cache stats)
- JS heap (GC live count, total allocated, collection stats)
- Glyph atlas (pages allocated, utilization percentage)
- Network buffers (connection pool size, TLS session cache)
- Display list (command count, estimated bytes)
- Debug stats command: expose memory stats via a debug interface (e.g.,
about:memorypage or console command) - Optimization: String interning for DOM tag names, attribute names, CSS property names — these repeat heavily
- Optimization: Small-string optimization for short strings (e.g., class names, IDs) — inline up to 23 bytes
- Optimization: Arena allocation for layout boxes — allocate from a bump arena per layout pass, free all at once
- Optimization: ComputedStyle size reduction — audit the ~120-field struct, use bitflags for boolean properties, pack enums tightly
- Optimization: Display list compaction — reuse display list buffer between frames (clear + refill instead of drop + alloc)
- GC tuning: adjust collection thresholds based on profiling data; consider generational hints
- Document findings: which subsystems use the most memory, what optimizations had the biggest impact
Implementation Notes#
- Start by adding
fn memory_usage(&self) -> usizemethods to key structures - Use
std::mem::size_ofand manual counting for heap allocations - String interning: a global
HashMap<String, InternedId>withInternedId = u32— store IDs instead of strings - Arena allocator: simple bump allocator (
Vec<u8>with a pointer) — no need for a full allocator crate - For ComputedStyle: many CSS properties have a small number of variants — use
u8enums and bitfields - Profile on real pages (load a few popular sites) to find actual bottlenecks vs. theoretical ones
- All optimizations must maintain correctness — run full test suite after each change
Dependencies#
- Should be done after: all other Phase 15 issues (benefits from seeing the full picture)
Phase#
Phase 15: Performance