Skip to content

Commit da7f3bc

Browse files
committed
perf(compile): read embedded files as static references
1 parent 6700ca8 commit da7f3bc

18 files changed

+102
-55
lines changed

cli/args/deno_json.rs

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ impl<'a> deno_config::fs::DenoConfigFs for DenoConfigFsAdapter<'a> {
2222
self
2323
.0
2424
.read_text_file_lossy_sync(path, None)
25+
// todo(https://github.com/denoland/deno_config/pull/140): avoid clone
26+
.map(|s| s.into_owned())
2527
.map_err(|err| err.into_io_error())
2628
}
2729

cli/cache/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ impl<'a> deno_cache_dir::DenoCacheEnv for DenoCacheEnvFsAdapter<'a> {
116116
self
117117
.0
118118
.read_file_sync(path, None)
119+
// todo(https://github.com/denoland/deno_cache_dir/pull/66): avoid clone
120+
.map(|bytes| bytes.into_owned())
119121
.map_err(|err| err.into_io_error())
120122
}
121123

cli/module_loader.rs

+16-10
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,10 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
10631063
self.npm_resolver.ensure_read_permission(permissions, path)
10641064
}
10651065

1066-
fn load_text_file_lossy(&self, path: &Path) -> Result<String, AnyError> {
1066+
fn load_text_file_lossy(
1067+
&self,
1068+
path: &Path,
1069+
) -> Result<Cow<'static, str>, AnyError> {
10671070
// todo(dsherret): use the preloaded module from the graph if available?
10681071
let media_type = MediaType::from_path(path);
10691072
let text = self.fs.read_text_file_lossy_sync(path, None)?;
@@ -1078,15 +1081,18 @@ impl<TGraphContainer: ModuleGraphContainer> NodeRequireLoader
10781081
.into(),
10791082
);
10801083
}
1081-
self.emitter.emit_parsed_source_sync(
1082-
&specifier,
1083-
media_type,
1084-
// this is probably not super accurate due to require esm, but probably ok.
1085-
// If we find this causes a lot of churn in the emit cache then we should
1086-
// investigate how we can make this better
1087-
ModuleKind::Cjs,
1088-
&text.into(),
1089-
)
1084+
self
1085+
.emitter
1086+
.emit_parsed_source_sync(
1087+
&specifier,
1088+
media_type,
1089+
// this is probably not super accurate due to require esm, but probably ok.
1090+
// If we find this causes a lot of churn in the emit cache then we should
1091+
// investigate how we can make this better
1092+
ModuleKind::Cjs,
1093+
&text.into(),
1094+
)
1095+
.map(Cow::Owned)
10901096
} else {
10911097
Ok(text)
10921098
}

cli/node.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ impl CjsCodeAnalyzer for CliCjsCodeAnalyzer {
160160
if let Ok(source_from_file) =
161161
self.fs.read_text_file_lossy_async(path, None).await
162162
{
163-
Cow::Owned(source_from_file)
163+
source_from_file
164164
} else {
165165
return Ok(ExtNodeCjsAnalysis::Cjs(CjsAnalysisExports {
166166
exports: vec![],

cli/resolver.rs

+11-5
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use crate::node::CliNodeCodeTranslator;
3838
use crate::npm::CliNpmResolver;
3939
use crate::npm::InnerCliNpmResolverRef;
4040
use crate::util::sync::AtomicFlag;
41-
use crate::util::text_encoding::from_utf8_lossy_owned;
41+
use crate::util::text_encoding::from_utf8_lossy_cow;
4242

4343
pub type CjsTracker = deno_resolver::cjs::CjsTracker<DenoFsNodeResolverEnv>;
4444
pub type IsCjsResolver =
@@ -64,7 +64,10 @@ pub struct ModuleCodeStringSource {
6464
pub struct CliDenoResolverFs(pub Arc<dyn FileSystem>);
6565

6666
impl deno_resolver::fs::DenoResolverFs for CliDenoResolverFs {
67-
fn read_to_string_lossy(&self, path: &Path) -> std::io::Result<String> {
67+
fn read_to_string_lossy(
68+
&self,
69+
path: &Path,
70+
) -> std::io::Result<Cow<'static, str>> {
6871
self
6972
.0
7073
.read_text_file_lossy_sync(path, None)
@@ -184,18 +187,21 @@ impl NpmModuleLoader {
184187

185188
let code = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
186189
// translate cjs to esm if it's cjs and inject node globals
187-
let code = from_utf8_lossy_owned(code);
190+
let code = from_utf8_lossy_cow(code);
188191
ModuleSourceCode::String(
189192
self
190193
.node_code_translator
191-
.translate_cjs_to_esm(specifier, Some(Cow::Owned(code)))
194+
.translate_cjs_to_esm(specifier, Some(code))
192195
.await?
193196
.into_owned()
194197
.into(),
195198
)
196199
} else {
197200
// esm and json code is untouched
198-
ModuleSourceCode::Bytes(code.into_boxed_slice().into())
201+
ModuleSourceCode::Bytes(match code {
202+
Cow::Owned(bytes) => bytes.into_boxed_slice().into(),
203+
Cow::Borrowed(bytes) => bytes.into(),
204+
})
199205
};
200206

201207
Ok(ModuleCodeStringSource {

cli/standalone/binary.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -280,14 +280,13 @@ impl StandaloneModules {
280280
.vfs
281281
.read_file_all(entry, VfsFileSubDataKind::ModuleGraph)?,
282282
Err(err) if err.kind() == ErrorKind::NotFound => {
283-
let bytes = match RealFs.read_file_sync(&path, None) {
283+
match RealFs.read_file_sync(&path, None) {
284284
Ok(bytes) => bytes,
285285
Err(FsError::Io(err)) if err.kind() == ErrorKind::NotFound => {
286286
return Ok(None)
287287
}
288288
Err(err) => return Err(err.into()),
289-
};
290-
Cow::Owned(bytes)
289+
}
291290
}
292291
Err(err) => return Err(err.into()),
293292
};
@@ -692,7 +691,7 @@ impl<'a> DenoCompileBinaryWriter<'a> {
692691
&file_path,
693692
match maybe_source {
694693
Some(source) => source,
695-
None => RealFs.read_file_sync(&file_path, None)?,
694+
None => RealFs.read_file_sync(&file_path, None)?.into_owned(),
696695
},
697696
VfsFileSubDataKind::ModuleGraph,
698697
)

cli/standalone/mod.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ use crate::resolver::IsCjsResolverOptions;
9191
use crate::resolver::NpmModuleLoader;
9292
use crate::util::progress_bar::ProgressBar;
9393
use crate::util::progress_bar::ProgressBarStyle;
94+
use crate::util::text_encoding::from_utf8_lossy_cow;
9495
use crate::util::v8::construct_v8_flags;
9596
use crate::worker::CliCodeCache;
9697
use crate::worker::CliMainWorkerFactory;
@@ -516,13 +517,13 @@ impl NodeRequireLoader for EmbeddedModuleLoader {
516517
fn load_text_file_lossy(
517518
&self,
518519
path: &std::path::Path,
519-
) -> Result<String, AnyError> {
520+
) -> Result<Cow<'static, str>, AnyError> {
520521
let file_entry = self.shared.vfs.file_entry(path)?;
521522
let file_bytes = self
522523
.shared
523524
.vfs
524525
.read_file_all(file_entry, VfsFileSubDataKind::ModuleGraph)?;
525-
Ok(String::from_utf8(file_bytes.into_owned())?)
526+
Ok(from_utf8_lossy_cow(file_bytes))
526527
}
527528

528529
fn is_maybe_cjs(

cli/standalone/virtual_fs.rs

+4-7
Original file line numberDiff line numberDiff line change
@@ -743,15 +743,12 @@ impl deno_io::fs::File for FileBackedVfsFile {
743743
Err(FsError::NotSupported)
744744
}
745745

746-
fn read_all_sync(self: Rc<Self>) -> FsResult<Vec<u8>> {
747-
self.read_to_end().map(|bytes| bytes.into_owned())
746+
fn read_all_sync(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
747+
self.read_to_end()
748748
}
749-
async fn read_all_async(self: Rc<Self>) -> FsResult<Vec<u8>> {
749+
async fn read_all_async(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>> {
750750
let inner = (*self).clone();
751-
tokio::task::spawn_blocking(move || {
752-
inner.read_to_end().map(|bytes| bytes.into_owned())
753-
})
754-
.await?
751+
tokio::task::spawn_blocking(move || inner.read_to_end()).await?
755752
}
756753

757754
fn chmod_sync(self: Rc<Self>, _pathmode: u32) -> FsResult<()> {

cli/util/text_encoding.rs

+9
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ use deno_core::ModuleSourceCode;
1111
static SOURCE_MAP_PREFIX: &[u8] =
1212
b"//# sourceMappingURL=data:application/json;base64,";
1313

14+
#[inline(always)]
15+
pub fn from_utf8_lossy_cow<'a>(bytes: Cow<'a, [u8]>) -> Cow<'a, str> {
16+
match bytes {
17+
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
18+
Cow::Owned(bytes) => Cow::Owned(from_utf8_lossy_owned(bytes)),
19+
}
20+
}
21+
22+
#[inline(always)]
1423
pub fn from_utf8_lossy_owned(bytes: Vec<u8>) -> String {
1524
match String::from_utf8_lossy(&bytes) {
1625
Cow::Owned(code) => code,

ext/fs/in_memory_fs.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// Allow using Arc for this module.
44
#![allow(clippy::disallowed_types)]
55

6+
use std::borrow::Cow;
67
use std::collections::hash_map::Entry;
78
use std::collections::HashMap;
89
use std::io::Error;
@@ -457,11 +458,11 @@ impl FileSystem for InMemoryFs {
457458
&self,
458459
path: &Path,
459460
_access_check: Option<AccessCheckCb>,
460-
) -> FsResult<Vec<u8>> {
461+
) -> FsResult<Cow<'static, [u8]>> {
461462
let entry = self.get_entry(path);
462463
match entry {
463464
Some(entry) => match &*entry {
464-
PathEntry::File(data) => Ok(data.clone()),
465+
PathEntry::File(data) => Ok(Cow::Owned(data.clone())),
465466
PathEntry::Dir => Err(FsError::Io(Error::new(
466467
ErrorKind::InvalidInput,
467468
"Is a directory",
@@ -474,7 +475,7 @@ impl FileSystem for InMemoryFs {
474475
&'a self,
475476
path: PathBuf,
476477
access_check: Option<AccessCheckCb<'a>>,
477-
) -> FsResult<Vec<u8>> {
478+
) -> FsResult<Cow<'static, [u8]>> {
478479
self.read_file_sync(&path, access_check)
479480
}
480481
}

ext/fs/interface.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
22

3+
use core::str;
34
use std::borrow::Cow;
45
use std::path::Path;
56
use std::path::PathBuf;
@@ -288,7 +289,7 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
288289
&self,
289290
path: &Path,
290291
access_check: Option<AccessCheckCb>,
291-
) -> FsResult<Vec<u8>> {
292+
) -> FsResult<Cow<'static, [u8]>> {
292293
let options = OpenOptions::read();
293294
let file = self.open_sync(path, options, access_check)?;
294295
let buf = file.read_all_sync()?;
@@ -298,7 +299,7 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
298299
&'a self,
299300
path: PathBuf,
300301
access_check: Option<AccessCheckCb<'a>>,
301-
) -> FsResult<Vec<u8>> {
302+
) -> FsResult<Cow<'static, [u8]>> {
302303
let options = OpenOptions::read();
303304
let file = self.open_async(path, options, access_check).await?;
304305
let buf = file.read_all_async().await?;
@@ -327,17 +328,25 @@ pub trait FileSystem: std::fmt::Debug + MaybeSend + MaybeSync {
327328
&self,
328329
path: &Path,
329330
access_check: Option<AccessCheckCb>,
330-
) -> FsResult<String> {
331+
) -> FsResult<Cow<'static, str>> {
331332
let buf = self.read_file_sync(path, access_check)?;
332-
Ok(string_from_utf8_lossy(buf))
333+
Ok(string_from_cow_utf8_lossy(buf))
333334
}
334335
async fn read_text_file_lossy_async<'a>(
335336
&'a self,
336337
path: PathBuf,
337338
access_check: Option<AccessCheckCb<'a>>,
338-
) -> FsResult<String> {
339+
) -> FsResult<Cow<'static, str>> {
339340
let buf = self.read_file_async(path, access_check).await?;
340-
Ok(string_from_utf8_lossy(buf))
341+
Ok(string_from_cow_utf8_lossy(buf))
342+
}
343+
}
344+
345+
#[inline(always)]
346+
fn string_from_cow_utf8_lossy(buf: Cow<'static, [u8]>) -> Cow<'static, str> {
347+
match buf {
348+
Cow::Owned(buf) => Cow::Owned(string_from_utf8_lossy(buf)),
349+
Cow::Borrowed(buf) => String::from_utf8_lossy(buf),
341350
}
342351
}
343352

ext/fs/ops.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
22

3+
use std::borrow::Cow;
34
use std::cell::RefCell;
45
use std::error::Error;
56
use std::fmt::Formatter;
@@ -1333,7 +1334,8 @@ where
13331334
.read_file_sync(&path, Some(&mut access_check))
13341335
.map_err(|error| map_permission_error("readfile", error, &path))?;
13351336

1336-
Ok(buf.into())
1337+
// todo(THIS PR): how to not clone here?
1338+
Ok(buf.into_owned().into_boxed_slice().into())
13371339
}
13381340

13391341
#[op2(async, stack_trace)]
@@ -1375,15 +1377,16 @@ where
13751377
.map_err(|error| map_permission_error("readfile", error, &path))?
13761378
};
13771379

1378-
Ok(buf.into())
1380+
// todo(THIS PR): how to not clone here?
1381+
Ok(buf.into_owned().into_boxed_slice().into())
13791382
}
13801383

13811384
#[op2(stack_trace)]
13821385
#[string]
13831386
pub fn op_fs_read_file_text_sync<P>(
13841387
state: &mut OpState,
13851388
#[string] path: String,
1386-
) -> Result<String, FsOpsError>
1389+
) -> Result<Cow<'static, str>, FsOpsError>
13871390
where
13881391
P: FsPermissions + 'static,
13891392
{
@@ -1405,7 +1408,7 @@ pub async fn op_fs_read_file_text_async<P>(
14051408
state: Rc<RefCell<OpState>>,
14061409
#[string] path: String,
14071410
#[smi] cancel_rid: Option<ResourceId>,
1408-
) -> Result<String, FsOpsError>
1411+
) -> Result<Cow<'static, str>, FsOpsError>
14091412
where
14101413
P: FsPermissions + 'static,
14111414
{

ext/fs/std_fs.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#![allow(clippy::disallowed_methods)]
44

5+
use std::borrow::Cow;
56
use std::env::current_dir;
67
use std::fs;
78
use std::io;
@@ -371,7 +372,7 @@ impl FileSystem for RealFs {
371372
&self,
372373
path: &Path,
373374
access_check: Option<AccessCheckCb>,
374-
) -> FsResult<Vec<u8>> {
375+
) -> FsResult<Cow<'static, [u8]>> {
375376
let mut file = open_with_access_check(
376377
OpenOptions {
377378
read: true,
@@ -382,13 +383,13 @@ impl FileSystem for RealFs {
382383
)?;
383384
let mut buf = Vec::new();
384385
file.read_to_end(&mut buf)?;
385-
Ok(buf)
386+
Ok(Cow::Owned(buf))
386387
}
387388
async fn read_file_async<'a>(
388389
&'a self,
389390
path: PathBuf,
390391
access_check: Option<AccessCheckCb<'a>>,
391-
) -> FsResult<Vec<u8>> {
392+
) -> FsResult<Cow<'static, [u8]>> {
392393
let mut file = open_with_access_check(
393394
OpenOptions {
394395
read: true,
@@ -400,7 +401,7 @@ impl FileSystem for RealFs {
400401
spawn_blocking(move || {
401402
let mut buf = Vec::new();
402403
file.read_to_end(&mut buf)?;
403-
Ok::<_, FsError>(buf)
404+
Ok::<_, FsError>(Cow::Owned(buf))
404405
})
405406
.await?
406407
.map_err(Into::into)

ext/io/fs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,8 @@ pub trait File {
215215
fn write_all_sync(self: Rc<Self>, buf: &[u8]) -> FsResult<()>;
216216
async fn write_all(self: Rc<Self>, buf: BufView) -> FsResult<()>;
217217

218-
fn read_all_sync(self: Rc<Self>) -> FsResult<Vec<u8>>;
219-
async fn read_all_async(self: Rc<Self>) -> FsResult<Vec<u8>>;
218+
fn read_all_sync(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>>;
219+
async fn read_all_async(self: Rc<Self>) -> FsResult<Cow<'static, [u8]>>;
220220

221221
fn chmod_sync(self: Rc<Self>, pathmode: u32) -> FsResult<()>;
222222
async fn chmod_async(self: Rc<Self>, mode: u32) -> FsResult<()>;

0 commit comments

Comments
 (0)