Skip to content

Commit 39c7d8d

Browse files
authored
refactor: faster args for op_load in TSC (#21438)
This commit changes the argument that "op_load" accepts, from a serde struct to "&str". This should equal to a slightly better performance.
1 parent f6b889b commit 39c7d8d

File tree

4 files changed

+29
-67
lines changed

4 files changed

+29
-67
lines changed

cli/build.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,11 @@ mod ts {
1313
use deno_core::op2;
1414
use deno_core::OpState;
1515
use deno_runtime::deno_node::SUPPORTED_BUILTIN_NODE_MODULES;
16-
use serde::Deserialize;
1716
use serde::Serialize;
1817
use std::collections::HashMap;
1918
use std::path::Path;
2019
use std::path::PathBuf;
2120

22-
#[derive(Debug, Deserialize)]
23-
struct LoadArgs {
24-
/// The fully qualified specifier that should be loaded.
25-
specifier: String,
26-
}
27-
2821
#[derive(Debug, Serialize)]
2922
#[serde(rename_all = "camelCase")]
3023
struct BuildInfoResponse {
@@ -81,15 +74,15 @@ mod ts {
8174
// files, but a slightly different implementation at build time.
8275
fn op_load(
8376
state: &mut OpState,
84-
#[serde] args: LoadArgs,
77+
#[string] load_specifier: &str,
8578
) -> Result<LoadResponse, AnyError> {
8679
let op_crate_libs = state.borrow::<HashMap<&str, PathBuf>>();
8780
let path_dts = state.borrow::<PathBuf>();
8881
let re_asset = lazy_regex::regex!(r"asset:/{3}lib\.(\S+)\.d\.ts");
8982
let build_specifier = "asset:///bootstrap.ts";
9083

9184
// we need a basic file to send to tsc to warm it up.
92-
if args.specifier == build_specifier {
85+
if load_specifier == build_specifier {
9386
Ok(LoadResponse {
9487
data: r#"Deno.writeTextFile("hello.txt", "hello deno!");"#.to_string(),
9588
version: "1".to_string(),
@@ -98,7 +91,7 @@ mod ts {
9891
})
9992
// specifiers come across as `asset:///lib.{lib_name}.d.ts` and we need to
10093
// parse out just the name so we can lookup the asset.
101-
} else if let Some(caps) = re_asset.captures(&args.specifier) {
94+
} else if let Some(caps) = re_asset.captures(load_specifier) {
10295
if let Some(lib) = caps.get(1).map(|m| m.as_str()) {
10396
// if it comes from an op crate, we were supplied with the path to the
10497
// file.
@@ -118,13 +111,13 @@ mod ts {
118111
} else {
119112
Err(custom_error(
120113
"InvalidSpecifier",
121-
format!("An invalid specifier was requested: {}", args.specifier),
114+
format!("An invalid specifier was requested: {}", load_specifier),
122115
))
123116
}
124117
} else {
125118
Err(custom_error(
126119
"InvalidSpecifier",
127-
format!("An invalid specifier was requested: {}", args.specifier),
120+
format!("An invalid specifier was requested: {}", load_specifier),
128121
))
129122
}
130123
}

cli/lsp/tsc.rs

+5-9
Original file line numberDiff line numberDiff line change
@@ -3835,12 +3835,6 @@ impl State {
38353835
}
38363836
}
38373837

3838-
#[derive(Debug, Deserialize, Serialize)]
3839-
#[serde(rename_all = "camelCase")]
3840-
struct SpecifierArgs {
3841-
specifier: String,
3842-
}
3843-
38443838
#[op2(fast)]
38453839
fn op_is_cancelled(state: &mut OpState) -> bool {
38463840
let state = state.borrow_mut::<State>();
@@ -3873,11 +3867,13 @@ struct LoadResponse {
38733867
fn op_load<'s>(
38743868
scope: &'s mut v8::HandleScope,
38753869
state: &mut OpState,
3876-
#[serde] args: SpecifierArgs,
3870+
#[string] specifier: &str,
38773871
) -> Result<v8::Local<'s, v8::Value>, AnyError> {
38783872
let state = state.borrow_mut::<State>();
3879-
let mark = state.performance.mark_with_args("tsc.op.op_load", &args);
3880-
let specifier = state.specifier_map.normalize(args.specifier)?;
3873+
let mark = state
3874+
.performance
3875+
.mark_with_args("tsc.op.op_load", specifier);
3876+
let specifier = state.specifier_map.normalize(specifier)?;
38813877
let maybe_load_response =
38823878
if specifier.as_str() == "internal:///missing_dependency.d.ts" {
38833879
Some(LoadResponse {

cli/tsc/99_main_compiler.js

+2-4
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ delete Object.prototype.__proto__;
525525
if (logDebug) {
526526
debug(`host.readFile("${specifier}")`);
527527
}
528-
return ops.op_load({ specifier }).data;
528+
return ops.op_load(specifier).data;
529529
},
530530
getCancellationToken() {
531531
// createLanguageService will call this immediately and cache it
@@ -555,9 +555,7 @@ delete Object.prototype.__proto__;
555555
}
556556

557557
/** @type {{ data: string; scriptKind: ts.ScriptKind; version: string; }} */
558-
const fileInfo = ops.op_load(
559-
{ specifier },
560-
);
558+
const fileInfo = ops.op_load(specifier);
561559
if (!fileInfo) {
562560
return undefined;
563561
}

cli/tsc/mod.rs

+17-42
Original file line numberDiff line numberDiff line change
@@ -414,12 +414,6 @@ fn op_emit(state: &mut OpState, #[serde] args: EmitArgs) -> bool {
414414
true
415415
}
416416

417-
#[derive(Debug, Deserialize)]
418-
struct LoadArgs {
419-
/// The fully qualified specifier that should be loaded.
420-
specifier: String,
421-
}
422-
423417
pub fn as_ts_script_kind(media_type: MediaType) -> i32 {
424418
match media_type {
425419
MediaType::JavaScript => 1,
@@ -453,36 +447,37 @@ struct LoadResponse {
453447
#[serde]
454448
fn op_load(
455449
state: &mut OpState,
456-
#[serde] v: LoadArgs,
450+
#[string] load_specifier: &str,
457451
) -> Result<LoadResponse, AnyError> {
458452
let state = state.borrow_mut::<State>();
459453

460-
let specifier = normalize_specifier(&v.specifier, &state.current_dir)
454+
let specifier = normalize_specifier(load_specifier, &state.current_dir)
461455
.context("Error converting a string module specifier for \"op_load\".")?;
462456

463457
let mut hash: Option<String> = None;
464458
let mut media_type = MediaType::Unknown;
465459
let graph = &state.graph;
466460

467-
let data = if &v.specifier == "internal:///.tsbuildinfo" {
461+
let data = if load_specifier == "internal:///.tsbuildinfo" {
468462
state.maybe_tsbuildinfo.as_deref().map(Cow::Borrowed)
469463
// in certain situations we return a "blank" module to tsc and we need to
470464
// handle the request for that module here.
471-
} else if &v.specifier == "internal:///missing_dependency.d.ts" {
465+
} else if load_specifier == "internal:///missing_dependency.d.ts" {
472466
hash = Some("1".to_string());
473467
media_type = MediaType::Dts;
474468
Some(Cow::Borrowed("declare const __: any;\nexport = __;\n"))
475-
} else if let Some(name) = v.specifier.strip_prefix("asset:///") {
469+
} else if let Some(name) = load_specifier.strip_prefix("asset:///") {
476470
let maybe_source = get_lazily_loaded_asset(name);
477471
hash = get_maybe_hash(maybe_source, state.hash_data);
478-
media_type = MediaType::from_str(&v.specifier);
472+
media_type = MediaType::from_str(load_specifier);
479473
maybe_source.map(Cow::Borrowed)
480474
} else {
481475
let specifier = if let Some(remapped_specifier) =
482-
state.remapped_specifiers.get(&v.specifier)
476+
state.remapped_specifiers.get(load_specifier)
483477
{
484478
remapped_specifier
485-
} else if let Some(remapped_specifier) = state.root_map.get(&v.specifier) {
479+
} else if let Some(remapped_specifier) = state.root_map.get(load_specifier)
480+
{
486481
remapped_specifier
487482
} else {
488483
&specifier
@@ -1062,13 +1057,8 @@ mod tests {
10621057
Some("some content".to_string()),
10631058
)
10641059
.await;
1065-
let actual = op_load::call(
1066-
&mut state,
1067-
LoadArgs {
1068-
specifier: "https://deno.land/x/mod.ts".to_string(),
1069-
},
1070-
)
1071-
.unwrap();
1060+
let actual =
1061+
op_load::call(&mut state, "https://deno.land/x/mod.ts").unwrap();
10721062
assert_eq!(
10731063
serde_json::to_value(actual).unwrap(),
10741064
json!({
@@ -1087,13 +1077,8 @@ mod tests {
10871077
Some("some content".to_string()),
10881078
)
10891079
.await;
1090-
let actual = op_load::call(
1091-
&mut state,
1092-
LoadArgs {
1093-
specifier: "asset:///lib.dom.d.ts".to_string(),
1094-
},
1095-
)
1096-
.expect("should have invoked op");
1080+
let actual = op_load::call(&mut state, "asset:///lib.dom.d.ts")
1081+
.expect("should have invoked op");
10971082
let expected = get_lazily_loaded_asset("lib.dom.d.ts").unwrap();
10981083
assert_eq!(actual.data.unwrap(), expected);
10991084
assert!(actual.version.is_some());
@@ -1108,13 +1093,8 @@ mod tests {
11081093
Some("some content".to_string()),
11091094
)
11101095
.await;
1111-
let actual = op_load::call(
1112-
&mut state,
1113-
LoadArgs {
1114-
specifier: "internal:///.tsbuildinfo".to_string(),
1115-
},
1116-
)
1117-
.expect("should have invoked op");
1096+
let actual = op_load::call(&mut state, "internal:///.tsbuildinfo")
1097+
.expect("should have invoked op");
11181098
assert_eq!(
11191099
serde_json::to_value(actual).unwrap(),
11201100
json!({
@@ -1128,13 +1108,8 @@ mod tests {
11281108
#[tokio::test]
11291109
async fn test_load_missing_specifier() {
11301110
let mut state = setup(None, None, None).await;
1131-
let actual = op_load::call(
1132-
&mut state,
1133-
LoadArgs {
1134-
specifier: "https://deno.land/x/mod.ts".to_string(),
1135-
},
1136-
)
1137-
.expect("should have invoked op");
1111+
let actual = op_load::call(&mut state, "https://deno.land/x/mod.ts")
1112+
.expect("should have invoked op");
11381113
assert_eq!(
11391114
serde_json::to_value(actual).unwrap(),
11401115
json!({

0 commit comments

Comments
 (0)