Skip to content

Commit

Permalink
perf: move from Buffer to zero-copy BufferSlice (#8574)
Browse files Browse the repository at this point in the history
  • Loading branch information
h-a-n-a authored Nov 29, 2024
1 parent 5d40770 commit 5a967f7
Show file tree
Hide file tree
Showing 7 changed files with 202 additions and 55 deletions.
16 changes: 14 additions & 2 deletions crates/node_binding/binding.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export declare class EntryOptionsDto {
export type EntryOptionsDTO = EntryOptionsDto

export declare class JsCompilation {
updateAsset(filename: string, newSourceOrFunction: JsCompatSource | ((source: JsCompatSource) => JsCompatSource), assetInfoUpdateOrFunction?: JsAssetInfo | ((assetInfo: JsAssetInfo) => JsAssetInfo)): void
updateAsset(filename: string, newSourceOrFunction: JsCompatSource | ((source: JsCompatSourceOwned) => JsCompatSourceOwned), assetInfoUpdateOrFunction?: JsAssetInfo | ((assetInfo: JsAssetInfo) => JsAssetInfo)): void
getAssets(): Readonly<JsAsset>[]
getAsset(name: string): JsAsset | null
getAssetSource(name: string): JsCompatSource | null
Expand Down Expand Up @@ -526,11 +526,23 @@ export interface JsCodegenerationResults {
map: Record<string, Record<string, JsCodegenerationResult>>
}

/**
* Zero copy `JsCompatSource` slice shared between Rust and Node.js if buffer is used.
*
* It can only be used in non-async context and the lifetime is bound to the fn closure.
*
* If you want to use Node.js Buffer in async context or want to extend the lifetime, use `JsCompatSourceOwned` instead.
*/
export interface JsCompatSource {
source: string | Buffer
map?: string
}

export interface JsCompatSourceOwned {
source: string | Buffer
map?: string
}

export interface JsCreateData {
request: string
userRequest: string
Expand Down Expand Up @@ -781,7 +793,7 @@ export interface JsRuntimeGlobals {
}

export interface JsRuntimeModule {
source?: JsCompatSource
source?: JsCompatSourceOwned
moduleIdentifier: string
constructorName: string
name: string
Expand Down
4 changes: 2 additions & 2 deletions crates/node_binding/src/plugins/interceptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use rspack_binding_values::{
JsFactorizeOutput, JsModuleWrapper, JsNormalModuleFactoryCreateModuleArgs, JsResolveArgs,
JsResolveForSchemeArgs, JsResolveForSchemeOutput, JsResolveOutput, JsRuntimeGlobals,
JsRuntimeModule, JsRuntimeModuleArg, JsRuntimeRequirementInTreeArg,
JsRuntimeRequirementInTreeResult, ToJsCompatSource,
JsRuntimeRequirementInTreeResult, ToJsCompatSourceOwned,
};
use rspack_collections::IdentifierSet;
use rspack_core::{
Expand Down Expand Up @@ -1256,7 +1256,7 @@ impl CompilationRuntimeModule for CompilationRuntimeModuleTap {
source: Some(
module
.generate(compilation)?
.to_js_compat_source()
.to_js_compat_source_owned()
.unwrap_or_else(|err| panic!("Failed to generate runtime module source: {err}")),
),
module_identifier: module.identifier().to_string(),
Expand Down
22 changes: 13 additions & 9 deletions crates/rspack_binding_values/src/compilation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,13 @@ use rspack_plugin_runtime::RuntimeModuleFromJs;
use super::{JsFilename, PathWithInfo};
use crate::utils::callbackify;
use crate::JsAddingRuntimeModule;
use crate::JsCompatSource;
use crate::JsModuleGraph;
use crate::JsModuleWrapper;
use crate::JsStatsOptimizationBailout;
use crate::LocalJsFilename;
use crate::ToJsCompatSource;
use crate::{
chunk::JsChunk, JsAsset, JsAssetInfo, JsChunkGroup, JsCompatSource, JsPathData, JsStats,
};
use crate::ToJsCompatSource as _;
use crate::{chunk::JsChunk, JsAsset, JsAssetInfo, JsChunkGroup, JsPathData, JsStats};
use crate::{JsRspackDiagnostic, JsRspackError};

#[napi]
Expand Down Expand Up @@ -72,10 +71,11 @@ impl JsCompilation {
#[napi]
impl JsCompilation {
#[napi(
ts_args_type = r#"filename: string, newSourceOrFunction: JsCompatSource | ((source: JsCompatSource) => JsCompatSource), assetInfoUpdateOrFunction?: JsAssetInfo | ((assetInfo: JsAssetInfo) => JsAssetInfo)"#
ts_args_type = r#"filename: string, newSourceOrFunction: JsCompatSource | ((source: JsCompatSourceOwned) => JsCompatSourceOwned), assetInfoUpdateOrFunction?: JsAssetInfo | ((assetInfo: JsAssetInfo) => JsAssetInfo)"#
)]
pub fn update_asset(
&mut self,
env: &Env,
filename: String,
new_source_or_function: Either<JsCompatSource, Function<'_, JsCompatSource, JsCompatSource>>,
asset_info_update_or_function: Option<
Expand All @@ -90,8 +90,8 @@ impl JsCompilation {
let new_source = match new_source_or_function {
Either::A(new_source) => new_source.into(),
Either::B(new_source_fn) => {
let js_compat_source: JsCompatSource =
new_source_fn.call(original_source.to_js_compat_source()?)?;
let js_compat_source =
new_source_fn.call(original_source.to_js_compat_source(env)?)?;
js_compat_source.into()
}
};
Expand Down Expand Up @@ -147,13 +147,17 @@ impl JsCompilation {
}

#[napi]
pub fn get_asset_source(&self, name: String) -> Result<Option<JsCompatSource>> {
pub fn get_asset_source<'a>(
&self,
env: &'a Env,
name: String,
) -> Result<Option<JsCompatSource<'a>>> {
let compilation = self.as_ref()?;

compilation
.assets()
.get(&name)
.and_then(|v| v.source.as_ref().map(|s| s.to_js_compat_source()))
.and_then(|v| v.source.as_ref().map(|s| s.to_js_compat_source(env)))
.transpose()
}

Expand Down
16 changes: 11 additions & 5 deletions crates/rspack_binding_values/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@ use rspack_plugin_runtime::RuntimeModuleFromJs;
use rspack_util::source_map::SourceMapKind;
use rustc_hash::FxHashMap as HashMap;

use super::{JsCompatSource, ToJsCompatSource};
use crate::{JsChunk, JsCodegenerationResults, JsDependenciesBlockWrapper, JsDependencyWrapper};
use super::JsCompatSourceOwned;
use crate::{
JsChunk, JsCodegenerationResults, JsCompatSource, JsDependenciesBlockWrapper,
JsDependencyWrapper, ToJsCompatSource,
};

#[derive(Default)]
#[napi(object)]
Expand Down Expand Up @@ -74,11 +77,14 @@ impl JsModule {
}

#[napi(getter)]
pub fn original_source(&mut self) -> napi::Result<Either<JsCompatSource, ()>> {
pub fn original_source<'a>(
&mut self,
env: &'a Env,
) -> napi::Result<Either<JsCompatSource<'a>, ()>> {
let module = self.as_ref()?;

Ok(match module.original_source() {
Some(source) => match source.to_js_compat_source().ok() {
Some(source) => match source.to_js_compat_source(env).ok() {
Some(s) => Either::A(s),
None => Either::B(()),
},
Expand Down Expand Up @@ -397,7 +403,7 @@ pub struct JsExecuteModuleArg {
#[derive(Default)]
#[napi(object)]
pub struct JsRuntimeModule {
pub source: Option<JsCompatSource>,
pub source: Option<JsCompatSourceOwned>,
pub module_identifier: String,
pub constructor_name: String,
pub name: String,
Expand Down
Loading

2 comments on commit 5a967f7

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Benchmark detail: Open

Name Base (2024-11-29 d249e62) Current Change
10000_big_production-mode_disable-minimize + exec 42.6 s ± 1.08 s 42.5 s ± 708 ms -0.42 %
10000_development-mode + exec 1.8 s ± 43 ms 1.79 s ± 32 ms -0.69 %
10000_development-mode_hmr + exec 645 ms ± 6.9 ms 645 ms ± 5.6 ms +0.03 %
10000_production-mode + exec 2.38 s ± 27 ms 2.38 s ± 43 ms +0.01 %
arco-pro_development-mode + exec 1.75 s ± 65 ms 1.77 s ± 96 ms +1.39 %
arco-pro_development-mode_hmr + exec 426 ms ± 1.1 ms 426 ms ± 0.68 ms -0.00 %
arco-pro_production-mode + exec 3.07 s ± 46 ms 3.15 s ± 195 ms +2.69 %
arco-pro_production-mode_generate-package-json-webpack-plugin + exec 3.12 s ± 55 ms 3.17 s ± 75 ms +1.79 %
threejs_development-mode_10x + exec 1.62 s ± 20 ms 1.62 s ± 19 ms +0.27 %
threejs_development-mode_10x_hmr + exec 809 ms ± 17 ms 806 ms ± 9.6 ms -0.38 %
threejs_production-mode_10x + exec 4.92 s ± 16 ms 4.92 s ± 36 ms +0.16 %
10000_big_production-mode_disable-minimize + rss memory 13340 MiB ± 244 MiB 13569 MiB ± 292 MiB +1.72 %
10000_development-mode + rss memory 797 MiB ± 76.8 MiB 785 MiB ± 46.7 MiB -1.55 %
10000_development-mode_hmr + rss memory 2088 MiB ± 191 MiB 2165 MiB ± 248 MiB +3.70 %
10000_production-mode + rss memory 684 MiB ± 31.4 MiB 679 MiB ± 50.2 MiB -0.76 %
arco-pro_development-mode + rss memory 731 MiB ± 51.8 MiB 739 MiB ± 33.9 MiB +1.14 %
arco-pro_development-mode_hmr + rss memory 964 MiB ± 132 MiB 924 MiB ± 152 MiB -4.13 %
arco-pro_production-mode + rss memory 880 MiB ± 50 MiB 860 MiB ± 47 MiB -2.22 %
arco-pro_production-mode_generate-package-json-webpack-plugin + rss memory 892 MiB ± 72.2 MiB 881 MiB ± 45.6 MiB -1.24 %
threejs_development-mode_10x + rss memory 823 MiB ± 48.6 MiB 821 MiB ± 43.3 MiB -0.25 %
threejs_development-mode_10x_hmr + rss memory 1950 MiB ± 458 MiB 2225 MiB ± 131 MiB +14.08 %
threejs_production-mode_10x + rss memory 1067 MiB ± 69.2 MiB 1044 MiB ± 62.1 MiB -2.09 %

@rspack-bot
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Ran ecosystem CI: Open

suite result
modernjs ✅ success
_selftest ✅ success
rsdoctor ✅ success
rspress ✅ success
rslib ❌ failure
rsbuild ✅ success
examples ✅ success
devserver ✅ success
nuxt ✅ success

Please sign in to comment.