Skip to content

Commit c4e1e62

Browse files
committed
Optimize
1 parent 10285bd commit c4e1e62

File tree

1 file changed

+16
-48
lines changed

1 file changed

+16
-48
lines changed

src/codegen/Codegen.ts

Lines changed: 16 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -69,32 +69,6 @@ function cloneTree(tree: NodeTree): NodeTree {
6969
}
7070
}
7171

72-
// Limited-concurrency worker pool for children processing.
73-
// Preserves output order while allowing N async operations in flight.
74-
const BUILD_CONCURRENCY = 2
75-
76-
async function mapConcurrent<T, R>(
77-
items: readonly T[],
78-
fn: (item: T, index: number) => Promise<R>,
79-
concurrency: number,
80-
): Promise<R[]> {
81-
if (items.length === 0) return []
82-
const results: R[] = new Array(items.length)
83-
let nextIndex = 0
84-
85-
async function worker() {
86-
while (nextIndex < items.length) {
87-
const i = nextIndex++
88-
results[i] = await fn(items[i], i)
89-
}
90-
}
91-
92-
await Promise.all(
93-
Array.from({ length: Math.min(concurrency, items.length) }, () => worker()),
94-
)
95-
return results
96-
}
97-
9872
export class Codegen {
9973
components: Map<
10074
string,
@@ -326,18 +300,15 @@ export class Codegen {
326300
)
327301
}
328302

329-
// Build children with limited concurrency (2 workers).
330-
// getProps(node) is already in-flight concurrently above.
331-
// With variable/text-style/getProps caches in place, Figma API contention is low enough
332-
// for 2 concurrent subtree builds. This roughly halves wall-clock for wide trees.
333-
const children: NodeTree[] =
334-
'children' in node
335-
? await mapConcurrent(
336-
node.children,
337-
(child) => this.buildTree(child),
338-
BUILD_CONCURRENCY,
339-
)
340-
: []
303+
// Build children sequentially — Figma's single-threaded IPC means
304+
// concurrent subtree builds add overhead without improving throughput,
305+
// and sequential order maximizes cache hits for shared nodes.
306+
const children: NodeTree[] = []
307+
if ('children' in node) {
308+
for (const child of node.children) {
309+
children.push(await this.buildTree(child))
310+
}
311+
}
341312

342313
// Now await props (likely already resolved while children were processing)
343314
const props = await propsPromise
@@ -417,16 +388,13 @@ export class Codegen {
417388
const t = perfStart()
418389
const selectorPropsPromise = getSelectorProps(node)
419390

420-
// Build children with limited concurrency (same as doBuildTree).
421-
// INSTANCE children are handled inside doBuildTree when buildTree(child) recurses.
422-
const childrenTrees: NodeTree[] =
423-
'children' in node
424-
? await mapConcurrent(
425-
node.children,
426-
(child) => this.buildTree(child),
427-
BUILD_CONCURRENCY,
428-
)
429-
: []
391+
// Build children sequentially (same reasoning as doBuildTree).
392+
const childrenTrees: NodeTree[] = []
393+
if ('children' in node) {
394+
for (const child of node.children) {
395+
childrenTrees.push(await this.buildTree(child))
396+
}
397+
}
430398

431399
// Await props + selectorProps (likely already resolved while children built)
432400
const [props, selectorProps] = await Promise.all([

0 commit comments

Comments
 (0)