dependency-graph

2 posts

figma

Improving Performance in the Layers Panel | Figma Blog (opens in new tab)

Figma rebuilt its layers panel to handle files containing tens of thousands of layers. The old architecture recomputed too much data too often, slowing both panel interactions and broader editor operations. A two-pass computation model and cached derived properties now make some interactions 30–50% faster. ## Why the Original Architecture Slowed Down - Figma files are trees of nodes with properties and children. - The panel previously built a large JavaScript object in one recursive pass. - Every expanded node—and often all of its descendants—had its display data recomputed after changes. - This created two problems: - Data was computed for hundreds of thousands of nodes even though only 20–30 rows were visible. - Small changes, such as expanding a node, triggered broad recomputation because incremental results were rarely cached. ## Two-Pass Computation - The first pass computes only the ordered list of row IDs shown in the panel. - Determining that order still requires handling complex rules, including: - Reversed child ordering in autolayout frames. - Node types such as widgets and FigJam stickies that hide children. - Fixed and scrolling headers that divide prototype-frame children. - Sticky top-level frames and components. - The second pass gathers display data—names, icons, lock and visibility state, and selection state—only for rows inside the visible window. - This makes windowing effective: previously, Figma computed data for off-screen rows even though they were not rendered. ## Caching Derived Data - Figma introduced its “derived properties” platform primitive to avoid recomputing unchanged data. - Nodes store mutable fields, while other values are calculated from those fields and related properties. - For example, a node’s absolute position can be derived from its parent’s absolute position and its relative position: ```text Self.AbsolutePosition = Parent.AbsolutePosition + Self.RelativePosition ``` - Derived properties: - Track their dependencies through an optimized dependency graph. - Support different caching strategies balancing speed and memory. - Are lazy by default, computing values only when they are read. - Because the layers panel is itself a tree, this dependency-aware system lets Figma update only affected rows while keeping stable portions cached. Figma’s results show the value of combining virtualization with incremental, dependency-based computation: large hierarchical interfaces can remain responsive when they calculate only visible data and preserve everything that has not changed.

figma

Speeding Up File Load Times, One Page At A Time | Figma Blog (opens in new tab)

Figma improved file-loading performance by dynamically loading only the page a user opens instead of the entire file. This approach reflects user-perceived complexity, reduces memory usage, and avoids making small pages wait for unrelated content. For the slowest 5% of loads, the change reduced load times by 33%. ## Loading Content According to User Needs - Figma files can contain dozens of pages, hundreds of frames, components, styles, variables, and prototype screens. - Usage data showed that users often treat a file as an entire project but typically visit only a subset of its pages in one session. - Loading everything up front made a small page unnecessarily depend on the size of the whole file. - Dynamic loading lets Figma display the selected page first and fetch additional content only when needed. ## Cross-Page Read Dependencies - A Figma file is modeled as a tree of nodes, with nodes representing interactable layers and their properties. - Nodes can reference content located on other pages, creating cross-page dependencies. - An instance points to its backing component, which may be on another page; the component must be loaded before the instance can render correctly. - Styles and variables also create dependencies: - A fill style requires loading its corresponding style node. - A variable-based font size requires the variable node so the client can resolve the raw value. ## QueryGraph and Earlier Dynamic Loading - Figma had already developed dynamic loading for view-only files and prototypes. - Its QueryGraph framework stores dependency relationships as an in-memory graph. - The multiplayer system uses this graph to determine which parts of a file should be sent to connected clients. - Previous loading strategies included: - **Page-based canvas loading:** Load the selected page and its required dependencies, then fetch other pages on demand. - **Frame-based prototype loading:** Load the current prototype screen and preload reachable frames within a limited number of transitions. ## Performance Impact - The goal is for load times to trend downward even as files become larger and more feature-rich. - Dynamic loading improves both initial responsiveness and memory consumption. - The largest benefits appear in worst-case loads, with a reported 33% reduction for the slowest 5% of page loads. Figma’s approach demonstrates that large collaborative documents should be loaded according to the user’s immediate context, while dependency tracking ensures referenced content remains available when required.