From 3a51cc9265a13df6117bf7e1db587e0252583ab6 Mon Sep 17 00:00:00 2001 From: Cong-Cong Date: Fri, 10 Jan 2025 11:08:18 +0800 Subject: [PATCH] perf: VolatileValue --- crates/node_binding/binding.d.ts | 2 +- .../rspack_binding_values/src/dependency.rs | 12 ++--- packages/rspack/src/Dependency.ts | 12 ++++- packages/rspack/src/ModuleGraph.ts | 54 ++++++------------- packages/rspack/src/ModuleGraphConnection.ts | 13 ++++- packages/rspack/src/util/volatile.ts | 54 +++++++++++++++++++ 6 files changed, 99 insertions(+), 48 deletions(-) create mode 100644 packages/rspack/src/util/volatile.ts diff --git a/crates/node_binding/binding.d.ts b/crates/node_binding/binding.d.ts index 0f69cfa97a07..37e2f1cf3ba0 100644 --- a/crates/node_binding/binding.d.ts +++ b/crates/node_binding/binding.d.ts @@ -189,7 +189,7 @@ export declare class JsDependency { get request(): string | undefined get critical(): boolean set critical(val: boolean) - get ids(): Array | undefined + get ids(): Array | null } export declare class JsEntries { diff --git a/crates/rspack_binding_values/src/dependency.rs b/crates/rspack_binding_values/src/dependency.rs index 5bbc84d0dc12..e020bcc35ef3 100644 --- a/crates/rspack_binding_values/src/dependency.rs +++ b/crates/rspack_binding_values/src/dependency.rs @@ -102,7 +102,7 @@ impl JsDependency { } #[napi(getter)] - pub fn ids(&mut self, env: Env) -> napi::Result, ()>> { + pub fn ids(&mut self, env: Env) -> napi::Result>> { let (dependency, compilation) = self.as_ref()?; Ok(match compilation { @@ -114,7 +114,7 @@ impl JsDependency { .into_iter() .map(|atom| env.create_string(atom.as_str())) .collect::>>()?; - Either::A(ids) + Some(ids) } else if let Some(dependency) = dependency.downcast_ref::() { @@ -123,19 +123,19 @@ impl JsDependency { .into_iter() .map(|atom| env.create_string(atom.as_str())) .collect::>>()?; - Either::A(ids) + Some(ids) } else if let Some(dependency) = dependency.downcast_ref::() { let ids = dependency .get_ids(&module_graph) .into_iter() .map(|atom| env.create_string(atom.as_str())) .collect::>>()?; - Either::A(ids) + Some(ids) } else { - Either::B(()) + None } } - None => Either::B(()), + None => None, }) } } diff --git a/packages/rspack/src/Dependency.ts b/packages/rspack/src/Dependency.ts index 6bfd3f1a7c16..74745a9ba29a 100644 --- a/packages/rspack/src/Dependency.ts +++ b/packages/rspack/src/Dependency.ts @@ -1,4 +1,5 @@ import type { JsDependency } from "@rspack/binding"; +import { VolatileValue } from "./util/volatile"; const TO_BINDING_MAPPINGS = new WeakMap(); const BINDING_MAPPINGS = new WeakMap(); @@ -28,6 +29,7 @@ export const bindingDependencyFactory = { export class Dependency { #type: string | undefined; #category: string | undefined; + #ids = new VolatileValue(); get type(): string { if (this.#type === undefined) { @@ -71,10 +73,16 @@ export class Dependency { } } - get ids(): string[] | undefined { + get ids(): string[] | null { const binding = bindingDependencyFactory.getBinding(this); + if (this.#ids.get() !== undefined) { + return this.#ids.get()!; + } if (binding) { - return binding.ids; + const ids = binding.ids; + this.#ids.set(ids); + return ids; } + return null; } } diff --git a/packages/rspack/src/ModuleGraph.ts b/packages/rspack/src/ModuleGraph.ts index fc115b3f4333..d1c16259edc9 100644 --- a/packages/rspack/src/ModuleGraph.ts +++ b/packages/rspack/src/ModuleGraph.ts @@ -3,27 +3,7 @@ import { bindingDependencyFactory, Dependency } from "./Dependency"; import { ExportsInfo } from "./ExportsInfo"; import { Module } from "./Module"; import { ModuleGraphConnection } from "./ModuleGraphConnection"; - -class VolatileCache { - #map = new Map(); - - get(key: K): V | undefined { - return this.#map.get(key); - } - - set(key: K, value: V) { - if (this.#map.size === 0) { - queueMicrotask(() => { - this.#map.clear(); - }); - } - this.#map.set(key, value); - } - - has(key: K): boolean { - return this.#map.has(key); - } -} +import { VolatileMap } from "./util/volatile"; export default class ModuleGraph { static __from_binding(binding: JsModuleGraph) { @@ -31,10 +11,10 @@ export default class ModuleGraph { } #inner: JsModuleGraph; - #resolvedModuleMappings = new VolatileCache(); - #outgoingConnectionsMappings = new VolatileCache(); - #parentBlockIndexMappings = new VolatileCache(); - #isAsyncCache = new VolatileCache(); + #resolvedModuleMap = new VolatileMap(); + #outgoingConnectionsMap = new VolatileMap(); + #parentBlockIndexMap = new VolatileMap(); + #isAsyncMap = new VolatileMap(); private constructor(binding: JsModuleGraph) { this.#inner = binding; @@ -50,14 +30,14 @@ export default class ModuleGraph { } getResolvedModule(dependency: Dependency): Module | null { - if (this.#resolvedModuleMappings.get(dependency)) { - return this.#resolvedModuleMappings.get(dependency)!; + if (this.#resolvedModuleMap.get(dependency) !== undefined) { + return this.#resolvedModuleMap.get(dependency)!; } const depBinding = bindingDependencyFactory.getBinding(dependency); if (depBinding) { const binding = this.#inner.getResolvedModule(depBinding); const module = binding ? Module.__from_binding(binding) : null; - this.#resolvedModuleMappings.set(dependency, module); + this.#resolvedModuleMap.set(dependency, module); return module; } return null; @@ -93,35 +73,35 @@ export default class ModuleGraph { } getOutgoingConnections(module: Module): ModuleGraphConnection[] { - if (this.#outgoingConnectionsMappings.get(module)) { - return this.#outgoingConnectionsMappings.get(module)!; + if (this.#outgoingConnectionsMap.get(module)) { + return this.#outgoingConnectionsMap.get(module)!; } const connections = this.#inner .getOutgoingConnections(Module.__to_binding(module)) .map(binding => ModuleGraphConnection.__from_binding(binding)); - this.#outgoingConnectionsMappings.set(module, connections); + this.#outgoingConnectionsMap.set(module, connections); return connections; } getParentBlockIndex(dependency: Dependency): number { - if (this.#parentBlockIndexMappings.get(dependency)) { - return this.#parentBlockIndexMappings.get(dependency)!; + if (this.#parentBlockIndexMap.get(dependency) !== undefined) { + return this.#parentBlockIndexMap.get(dependency)!; } const depBinding = bindingDependencyFactory.getBinding(dependency); if (depBinding) { const index = this.#inner.getParentBlockIndex(depBinding); - this.#parentBlockIndexMappings.set(dependency, index); + this.#parentBlockIndexMap.set(dependency, index); return index; } return -1; } isAsync(module: Module): boolean { - if (this.#isAsyncCache.get(module)) { - return this.#isAsyncCache.get(module)!; + if (this.#isAsyncMap.get(module) !== undefined) { + return this.#isAsyncMap.get(module)!; } const result = this.#inner.isAsync(Module.__to_binding(module)); - this.#isAsyncCache.set(module, result); + this.#isAsyncMap.set(module, result); return result; } } diff --git a/packages/rspack/src/ModuleGraphConnection.ts b/packages/rspack/src/ModuleGraphConnection.ts index 1e6b18d8986b..7828020569cf 100644 --- a/packages/rspack/src/ModuleGraphConnection.ts +++ b/packages/rspack/src/ModuleGraphConnection.ts @@ -1,6 +1,7 @@ import type { JsModuleGraphConnection } from "@rspack/binding"; import { bindingDependencyFactory, Dependency } from "./Dependency"; import { Module } from "./Module"; +import { VolatileValue } from "./util/volatile"; const MODULE_GRAPH_CONNECTION_MAPPINGS = new WeakMap< JsModuleGraphConnection, @@ -12,6 +13,7 @@ export class ModuleGraphConnection { declare readonly dependency: Dependency; #inner: JsModuleGraphConnection; + #module: VolatileValue = new VolatileValue(); #dependency: Dependency | undefined; #resolvedModule: Module | undefined | null; @@ -35,8 +37,15 @@ export class ModuleGraphConnection { Object.defineProperties(this, { module: { enumerable: true, - get(): Module | null { - return binding.module ? Module.__from_binding(binding.module) : null; + get: (): Module | null => { + if (this.#module.get() !== undefined) { + return this.#module.get()!; + } + const module = binding.module + ? Module.__from_binding(binding.module) + : null; + this.#module.set(module); + return module; } }, dependency: { diff --git a/packages/rspack/src/util/volatile.ts b/packages/rspack/src/util/volatile.ts new file mode 100644 index 000000000000..2472312f8d18 --- /dev/null +++ b/packages/rspack/src/util/volatile.ts @@ -0,0 +1,54 @@ +class MicrotaskQueue { + #callbacks: (() => void)[] = []; + + queue(callback: () => void) { + if (this.#callbacks.length === 0) { + queueMicrotask(() => { + for (const cb of this.#callbacks) { + cb(); + } + }); + } + this.#callbacks.push(callback); + } +} + +const GLOBAL_MICROTASK_QUEUE = new MicrotaskQueue(); + +export class VolatileMap { + #map = new Map(); + + get(key: K): V | undefined { + return this.#map.get(key); + } + + set(key: K, value: V) { + if (this.#map.size === 0) { + GLOBAL_MICROTASK_QUEUE.queue(() => { + this.#map.clear(); + }); + } + this.#map.set(key, value); + } + + has(key: K): boolean { + return this.#map.has(key); + } +} + +export class VolatileValue { + #value: V | undefined = undefined; + + get(): V | undefined { + return this.#value; + } + + set(value: V) { + if (this.#value === undefined) { + GLOBAL_MICROTASK_QUEUE.queue(() => { + this.#value = undefined; + }); + } + this.#value = value; + } +}