Performance
Tips for keeping Taffy layouts blazing fast.
Taffy is designed to be efficient and high-performance, but specific patterns can affect performance.
1. Pre-Allocate Capacity
If you know the node count, use withCapacity to avoid re-allocations.
2. Incremental Layouts
Taffy reuses cached results when their inputs still match. Changing a node can also affect its ancestors and siblings, so a layout pass is not limited to the changed branch. Style and tree mutations invalidate relevant caches; in-place changes to measured content require markDirty(node) or setNodeContext(node, context).
Common Pitfalls
1. Excessive Nesting
Every level of depth adds complexity to the recursive algorithm.
- Bad:
View -> View -> View -> Buttonjust for padding. - Good: Use
paddingon the parent instead of wrapper nodes.
2. Deep Measurement Functions
Custom measure functions (for text/images) are called frequently.
- Optimize: Ensure your measurement callback is fast. Avoid DOM reflows or heavy calculations inside measurements.
Optimization Patterns
Reuse Styles
Creating Style objects allocates WASM memory. Reuse styles for nodes with the same rules; node creation copies the style, so the original can be freed once no longer needed. See Memory Management for owned style and layout copies.
// ✅ Good const tree = new TaffyTree(); const ITEM_STYLE = new Style({ flexGrow: 1 }); for (let i = 0; i < 1000; i++) { tree.newLeaf(ITEM_STYLE); } ITEM_STYLE.free();
// ❌ Avoid if items are identical const tree = new TaffyTree(); for (let i = 0; i < 1000; i++) { tree.newLeaf(new Style({ flexGrow: 1 })); }
Batch Property Access
Use batch getters and setters to minimize WASM bridge overhead.
Style Batch Update: Instead of setting properties one by one:
const style = new Style(); // ❌ Multiple calls = High overhead style.display = Display.Flex; style.width = 100; style.height = 100;
Use set():
const style = new Style(); // ✅ Single call = Low overhead style.set({ display: Display.Flex, width: 100, height: 100, });
Layout Batch Read: Instead of reading layout properties individually:
const tree = new TaffyTree(); const node = tree.newLeaf(new Style()); tree.computeLayout(node, { width: 100, height: 100 }); // ❌ Multiple calls const layout = tree.getLayout(node); const x = layout.x; const y = layout.y; const w = layout.width; const h = layout.height;
Use get():
const tree = new TaffyTree(); const node = tree.newLeaf(new Style()); tree.computeLayout(node, { width: 100, height: 100 }); // ✅ Single call returns array of values const layout = tree.getLayout(node); const [x, y, w, h] = layout.get("x", "y", "width", "height");
Benchmarking
Use performance.now() to measure your layout pass.
const tree = new TaffyTree(); const root = tree.newLeaf(new Style()); const start = performance.now(); tree.computeLayout(root, { width: 1000, height: 1000 }); const end = performance.now(); console.log(`Layout took ${end - start}ms`);