Supporting Faster File Load Times with Memory Optimizations in Rust | Figma Blog (opens in new tab)
Figma improved server-side file loading by reducing the memory overhead of its Rust data structures. Replacing per-node BTreeMaps with compact sorted vectors made deserialization faster and cut memory usage for large files by nearly 25%, despite worse theoretical operation complexity. The team also explored packing field IDs into unused pointer bits, potentially storing the same information in fewer bytes.
Smaller, Memory-Efficient Maps
- Figma files consist of nodes, each represented by properties such as type, parent, position, and dimensions.
- Nodes were stored as
BTreeMap<u16, u64 pointer>structures because ordered iteration was required for serialization. - Profiling showed these maps consumed more than 60% of a file’s memory, even though they stored metadata rather than large data payloads.
- The schema contains fewer than 200 possible fields, and nodes typically contain only a subset of them—about 60 properties on average.
- Figma replaced each
BTreeMapwith a sorted flat vector of(field ID, pointer)pairs. - Although vectors have theoretically slower insertion, lookup, and editing, their compact linear layout is more cache-friendly and faster during deserialization.
- The deployed change reduced memory usage by nearly 25% for large files and improved file-loading performance.
Saving More Memory with Bit Stuffing
- The team also investigated storing the field ID inside the pointer itself.
- While pointers are nominally 64 bits, x86 systems currently use only the lower 48 bits for memory addresses, leaving 16 bits available.
- Figma’s field IDs require exactly 16 bits, allowing a single
u64to contain both:- A 16-bit field ID
- A 48-bit memory pointer
- This representation could eliminate the separate field-ID storage and further reduce memory overhead.
- The approach had not yet been productionized because relying on unused pointer bits is architecture-dependent and could change in the future.
Figma’s results demonstrate that practical memory layout and CPU cache behavior can outweigh Big O complexity. For compact, bounded data structures, flat vectors—and carefully considered bit packing—can deliver substantial improvements in both memory efficiency and load speed.