mirror of
https://github.com/denoland/deno.git
synced 2024-12-24 08:09:08 -05:00
perf(runtime): flatten arguments for write_file ops (#15776)
This commit is contained in:
parent
264ad49e18
commit
1cdd2504b1
3 changed files with 65 additions and 63 deletions
21
cli/bench/write_file.js
Normal file
21
cli/bench/write_file.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
? Deno.args
|
||||||
|
: [process.argv[2], process.argv[3]];
|
||||||
|
|
||||||
|
total = total ? parseInt(total, 0) : 50;
|
||||||
|
count = count ? parseInt(count, 10) : 10000;
|
||||||
|
|
||||||
|
async function bench(fun) {
|
||||||
|
const start = Date.now();
|
||||||
|
for (let i = 0; i < count; i++) await fun();
|
||||||
|
const elapsed = Date.now() - start;
|
||||||
|
const rate = Math.floor(count / (elapsed / 1000));
|
||||||
|
console.log(`time ${elapsed} ms rate ${rate}`);
|
||||||
|
if (--total) queueMicrotask(() => bench(fun));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench(() => Deno.writeFile("/dev/null", new Uint8Array(10)));
|
||||||
|
// const fs = require("fs").promises;
|
||||||
|
// bench(() => fs.writeFile("/dev/null", new Uint8Array(10)));
|
|
@ -12,13 +12,13 @@
|
||||||
options = {},
|
options = {},
|
||||||
) {
|
) {
|
||||||
options.signal?.throwIfAborted();
|
options.signal?.throwIfAborted();
|
||||||
ops.op_write_file_sync({
|
ops.op_write_file_sync(
|
||||||
path: pathFromURL(path),
|
pathFromURL(path),
|
||||||
|
options.mode,
|
||||||
|
options.append ?? false,
|
||||||
|
options.create ?? true,
|
||||||
data,
|
data,
|
||||||
mode: options.mode,
|
);
|
||||||
append: options.append ?? false,
|
|
||||||
create: options.create ?? true,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function writeFile(
|
async function writeFile(
|
||||||
|
@ -35,14 +35,15 @@
|
||||||
options.signal[abortSignal.add](abortHandler);
|
options.signal[abortSignal.add](abortHandler);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await core.opAsync("op_write_file_async", {
|
await core.opAsync(
|
||||||
path: pathFromURL(path),
|
"op_write_file_async",
|
||||||
|
pathFromURL(path),
|
||||||
|
options.mode,
|
||||||
|
options.append ?? false,
|
||||||
|
options.create ?? true,
|
||||||
data,
|
data,
|
||||||
mode: options.mode,
|
|
||||||
append: options.append ?? false,
|
|
||||||
create: options.create ?? true,
|
|
||||||
cancelRid,
|
cancelRid,
|
||||||
});
|
);
|
||||||
} finally {
|
} finally {
|
||||||
if (options.signal) {
|
if (options.signal) {
|
||||||
options.signal[abortSignal.remove](abortHandler);
|
options.signal[abortSignal.remove](abortHandler);
|
||||||
|
|
|
@ -108,14 +108,6 @@ pub fn init() -> Extension {
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct OpenArgs {
|
|
||||||
path: String,
|
|
||||||
mode: Option<u32>,
|
|
||||||
options: OpenOptions,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Debug)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -222,58 +214,47 @@ async fn op_open_async(
|
||||||
Ok(rid)
|
Ok(rid)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[inline]
|
||||||
#[serde(rename_all = "camelCase")]
|
fn write_open_options(create: bool, append: bool) -> OpenOptions {
|
||||||
pub struct WriteFileArgs {
|
OpenOptions {
|
||||||
path: String,
|
read: false,
|
||||||
mode: Option<u32>,
|
write: true,
|
||||||
append: bool,
|
create,
|
||||||
create: bool,
|
truncate: !append,
|
||||||
data: ZeroCopyBuf,
|
append,
|
||||||
cancel_rid: Option<ResourceId>,
|
create_new: false,
|
||||||
}
|
|
||||||
|
|
||||||
impl WriteFileArgs {
|
|
||||||
fn into_open_args_and_data(self) -> (OpenArgs, ZeroCopyBuf) {
|
|
||||||
(
|
|
||||||
OpenArgs {
|
|
||||||
path: self.path,
|
|
||||||
mode: self.mode,
|
|
||||||
options: OpenOptions {
|
|
||||||
read: false,
|
|
||||||
write: true,
|
|
||||||
create: self.create,
|
|
||||||
truncate: !self.append,
|
|
||||||
append: self.append,
|
|
||||||
create_new: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
self.data,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
fn op_write_file_sync(
|
fn op_write_file_sync(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
args: WriteFileArgs,
|
path: String,
|
||||||
|
mode: Option<u32>,
|
||||||
|
append: bool,
|
||||||
|
create: bool,
|
||||||
|
data: ZeroCopyBuf,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let (open_args, data) = args.into_open_args_and_data();
|
|
||||||
let (path, open_options) = open_helper(
|
let (path, open_options) = open_helper(
|
||||||
state,
|
state,
|
||||||
&open_args.path,
|
&path,
|
||||||
open_args.mode,
|
mode,
|
||||||
Some(&open_args.options),
|
Some(&write_open_options(create, append)),
|
||||||
)?;
|
)?;
|
||||||
write_file(&path, open_options, &open_args, data)
|
write_file(&path, open_options, mode, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op]
|
||||||
async fn op_write_file_async(
|
async fn op_write_file_async(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
args: WriteFileArgs,
|
path: String,
|
||||||
|
mode: Option<u32>,
|
||||||
|
append: bool,
|
||||||
|
create: bool,
|
||||||
|
data: ZeroCopyBuf,
|
||||||
|
cancel_rid: Option<ResourceId>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let cancel_handle = match args.cancel_rid {
|
let cancel_handle = match cancel_rid {
|
||||||
Some(cancel_rid) => state
|
Some(cancel_rid) => state
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.resource_table
|
.resource_table
|
||||||
|
@ -281,15 +262,14 @@ async fn op_write_file_async(
|
||||||
.ok(),
|
.ok(),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let (open_args, data) = args.into_open_args_and_data();
|
|
||||||
let (path, open_options) = open_helper(
|
let (path, open_options) = open_helper(
|
||||||
&mut *state.borrow_mut(),
|
&mut *state.borrow_mut(),
|
||||||
&open_args.path,
|
&path,
|
||||||
open_args.mode,
|
mode,
|
||||||
Some(&open_args.options),
|
Some(&write_open_options(create, append)),
|
||||||
)?;
|
)?;
|
||||||
let write_future = tokio::task::spawn_blocking(move || {
|
let write_future = tokio::task::spawn_blocking(move || {
|
||||||
write_file(&path, open_options, &open_args, data)
|
write_file(&path, open_options, mode, data)
|
||||||
});
|
});
|
||||||
if let Some(cancel_handle) = cancel_handle {
|
if let Some(cancel_handle) = cancel_handle {
|
||||||
write_future.or_cancel(cancel_handle).await???;
|
write_future.or_cancel(cancel_handle).await???;
|
||||||
|
@ -302,7 +282,7 @@ async fn op_write_file_async(
|
||||||
fn write_file(
|
fn write_file(
|
||||||
path: &Path,
|
path: &Path,
|
||||||
open_options: std::fs::OpenOptions,
|
open_options: std::fs::OpenOptions,
|
||||||
_open_args: &OpenArgs,
|
_mode: Option<u32>,
|
||||||
data: ZeroCopyBuf,
|
data: ZeroCopyBuf,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
let mut std_file = open_options.open(path).map_err(|err| {
|
let mut std_file = open_options.open(path).map_err(|err| {
|
||||||
|
@ -311,7 +291,7 @@ fn write_file(
|
||||||
|
|
||||||
// need to chmod the file if it already exists and a mode is specified
|
// need to chmod the file if it already exists and a mode is specified
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
if let Some(mode) = &_open_args.mode {
|
if let Some(mode) = _mode {
|
||||||
use std::os::unix::fs::PermissionsExt;
|
use std::os::unix::fs::PermissionsExt;
|
||||||
let permissions = PermissionsExt::from_mode(mode & 0o777);
|
let permissions = PermissionsExt::from_mode(mode & 0o777);
|
||||||
std_file
|
std_file
|
||||||
|
|
Loading…
Reference in a new issue