Skip to content

Commit e1feefb

Browse files
committed
perf: chunk graph js api
1 parent 3a51cc9 commit e1feefb

File tree

6 files changed

+75
-37
lines changed

6 files changed

+75
-37
lines changed

packages/rspack/src/ChunkGraph.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,14 @@ import { Chunk } from "./Chunk";
44
import { Module } from "./Module";
55
import { DependenciesBlock } from "./DependenciesBlock";
66
import { ChunkGroup } from "./ChunkGroup";
7+
import { VolatileMap } from "./util/volatile";
78

89
export class ChunkGraph {
910
#inner: JsChunkGraph;
1011

12+
#chunkModulesMap = new VolatileMap<Chunk, ReadonlyArray<Module>>();
13+
#moduleIdMap = new VolatileMap<Module, string | null>();
14+
1115
static __from_binding(binding: JsChunkGraph): ChunkGraph {
1216
return new ChunkGraph(binding);
1317
}
@@ -17,15 +21,25 @@ export class ChunkGraph {
1721
}
1822

1923
getChunkModules(chunk: Chunk): ReadonlyArray<Module> {
20-
return this.#inner
21-
.getChunkModules(Chunk.__to_binding(chunk))
22-
.map(binding => Module.__from_binding(binding));
24+
let modules = this.#chunkModulesMap.get(chunk);
25+
if (modules === undefined) {
26+
modules = this.#inner
27+
.getChunkModules(Chunk.__to_binding(chunk))
28+
.map(binding => Module.__from_binding(binding));
29+
this.#chunkModulesMap.set(chunk, modules);
30+
}
31+
return modules;
2332
}
2433

2534
getChunkModulesIterable(chunk: Chunk): Iterable<Module> {
26-
return this.#inner
27-
.getChunkModules(Chunk.__to_binding(chunk))
28-
.map(binding => Module.__from_binding(binding));
35+
let modules = this.#chunkModulesMap.get(chunk);
36+
if (modules === undefined) {
37+
modules = this.#inner
38+
.getChunkModules(Chunk.__to_binding(chunk))
39+
.map(binding => Module.__from_binding(binding));
40+
this.#chunkModulesMap.set(chunk, modules);
41+
}
42+
return modules;
2943
}
3044

3145
getChunkEntryModulesIterable(chunk: Chunk): Iterable<Module> {
@@ -65,7 +79,12 @@ export class ChunkGraph {
6579
}
6680

6781
getModuleId(module: Module): string | null {
68-
return this.#inner.getModuleId(Module.__to_binding(module));
82+
let moduleId = this.#moduleIdMap.get(module);
83+
if (moduleId === undefined) {
84+
moduleId = this.#inner.getModuleId(Module.__to_binding(module));
85+
this.#moduleIdMap.set(module, moduleId);
86+
}
87+
return moduleId;
6988
}
7089

7190
getBlockChunkGroup(depBlock: DependenciesBlock): ChunkGroup | null {

packages/rspack/src/ChunkGroup.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { JsChunkGroup } from "@rspack/binding";
22

33
import { Chunk } from "./Chunk";
44
import { Module } from "./Module";
5+
import { VolatileValue } from "./util/volatile";
56

67
const CHUNK_GROUP_MAPPINGS = new WeakMap<JsChunkGroup, ChunkGroup>();
78

@@ -14,6 +15,8 @@ export class ChunkGroup {
1415

1516
#inner: JsChunkGroup;
1617

18+
#name = new VolatileValue<string | undefined>();
19+
1720
static __from_binding(binding: JsChunkGroup) {
1821
let chunkGroup = CHUNK_GROUP_MAPPINGS.get(binding);
1922
if (chunkGroup) {
@@ -45,7 +48,12 @@ export class ChunkGroup {
4548
name: {
4649
enumerable: true,
4750
get: () => {
48-
return this.#inner.name;
51+
if (this.#name.has()) {
52+
return this.#name.get();
53+
}
54+
const name = this.#inner.name;
55+
this.#name.set(name);
56+
return name;
4957
}
5058
},
5159
origins: {

packages/rspack/src/Dependency.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ export class Dependency {
7575

7676
get ids(): string[] | null {
7777
const binding = bindingDependencyFactory.getBinding(this);
78-
if (this.#ids.get() !== undefined) {
78+
if (this.#ids.has()) {
7979
return this.#ids.get()!;
8080
}
8181
if (binding) {

packages/rspack/src/ModuleGraph.ts

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,18 @@ export default class ModuleGraph {
3030
}
3131

3232
getResolvedModule(dependency: Dependency): Module | null {
33-
if (this.#resolvedModuleMap.get(dependency) !== undefined) {
34-
return this.#resolvedModuleMap.get(dependency)!;
33+
let resolvedModule = this.#resolvedModuleMap.get(dependency);
34+
if (resolvedModule === undefined) {
35+
const depBinding = bindingDependencyFactory.getBinding(dependency);
36+
if (depBinding) {
37+
const binding = this.#inner.getResolvedModule(depBinding);
38+
resolvedModule = binding ? Module.__from_binding(binding) : null;
39+
this.#resolvedModuleMap.set(dependency, resolvedModule);
40+
} else {
41+
return null;
42+
}
3543
}
36-
const depBinding = bindingDependencyFactory.getBinding(dependency);
37-
if (depBinding) {
38-
const binding = this.#inner.getResolvedModule(depBinding);
39-
const module = binding ? Module.__from_binding(binding) : null;
40-
this.#resolvedModuleMap.set(dependency, module);
41-
return module;
42-
}
43-
return null;
44+
return resolvedModule;
4445
}
4546

4647
getParentModule(dependency: Dependency): Module | null {
@@ -73,27 +74,28 @@ export default class ModuleGraph {
7374
}
7475

7576
getOutgoingConnections(module: Module): ModuleGraphConnection[] {
76-
if (this.#outgoingConnectionsMap.get(module)) {
77-
return this.#outgoingConnectionsMap.get(module)!;
77+
let connections = this.#outgoingConnectionsMap.get(module);
78+
if (connections === undefined) {
79+
connections = this.#inner
80+
.getOutgoingConnections(Module.__to_binding(module))
81+
.map(binding => ModuleGraphConnection.__from_binding(binding));
82+
this.#outgoingConnectionsMap.set(module, connections);
7883
}
79-
const connections = this.#inner
80-
.getOutgoingConnections(Module.__to_binding(module))
81-
.map(binding => ModuleGraphConnection.__from_binding(binding));
82-
this.#outgoingConnectionsMap.set(module, connections);
8384
return connections;
8485
}
8586

8687
getParentBlockIndex(dependency: Dependency): number {
87-
if (this.#parentBlockIndexMap.get(dependency) !== undefined) {
88-
return this.#parentBlockIndexMap.get(dependency)!;
89-
}
90-
const depBinding = bindingDependencyFactory.getBinding(dependency);
91-
if (depBinding) {
92-
const index = this.#inner.getParentBlockIndex(depBinding);
93-
this.#parentBlockIndexMap.set(dependency, index);
94-
return index;
88+
let index = this.#parentBlockIndexMap.get(dependency);
89+
if (index === undefined) {
90+
const depBinding = bindingDependencyFactory.getBinding(dependency);
91+
if (depBinding) {
92+
index = this.#inner.getParentBlockIndex(depBinding);
93+
this.#parentBlockIndexMap.set(dependency, index);
94+
} else {
95+
return -1;
96+
}
9597
}
96-
return -1;
98+
return index;
9799
}
98100

99101
isAsync(module: Module): boolean {

packages/rspack/src/ModuleGraphConnection.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export class ModuleGraphConnection {
3838
module: {
3939
enumerable: true,
4040
get: (): Module | null => {
41-
if (this.#module.get() !== undefined) {
41+
if (this.#module.has()) {
4242
return this.#module.get()!;
4343
}
4444
const module = binding.module

packages/rspack/src/util/volatile.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ class MicrotaskQueue {
44
queue(callback: () => void) {
55
if (this.#callbacks.length === 0) {
66
queueMicrotask(() => {
7-
for (const cb of this.#callbacks) {
7+
const callbacks = this.#callbacks;
8+
this.#callbacks = [];
9+
for (const cb of callbacks) {
810
cb();
911
}
1012
});
@@ -37,18 +39,25 @@ export class VolatileMap<K, V> {
3739
}
3840

3941
export class VolatileValue<V> {
42+
#setted = false;
4043
#value: V | undefined = undefined;
4144

4245
get(): V | undefined {
4346
return this.#value;
4447
}
4548

4649
set(value: V) {
47-
if (this.#value === undefined) {
50+
if (!this.#setted) {
4851
GLOBAL_MICROTASK_QUEUE.queue(() => {
4952
this.#value = undefined;
53+
this.#setted = false;
5054
});
5155
}
5256
this.#value = value;
57+
this.#setted = true;
58+
}
59+
60+
has() {
61+
return this.#setted;
5362
}
5463
}

0 commit comments

Comments
 (0)