Skip to content

Commit

Permalink
perf: use fast ops for tty (#15976)
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy authored Sep 23, 2022
1 parent b5dfcbb commit 72af149
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 62 deletions.
21 changes: 21 additions & 0 deletions cli/bench/tty.js
Original file line number Diff line number Diff line change
@@ -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) : 100000;

function bench(fun) {
const start = Date.now();
for (let i = 0; i < count; i++) 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.consoleSize(0);
});
4 changes: 4 additions & 0 deletions ops/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,10 @@ fn can_be_fast_api(core: &TokenStream2, f: &syn::ItemFn) -> Option<FastApiSyn> {
args.push(arg);
}
None => match is_ref_slice(&ty) {
Some(SliceType::U32Mut) => {
args.push(quote! { #core::v8::fast_api::Type::TypedArray(#core::v8::fast_api::CType::Uint32) });
slices.insert(pos, quote!(u32));
}
Some(_) => {
args.push(quote! { #core::v8::fast_api::Type::TypedArray(#core::v8::fast_api::CType::Uint8) });
slices.insert(pos, quote!(u8));
Expand Down
20 changes: 12 additions & 8 deletions runtime/js/40_tty.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,28 @@
"use strict";

((window) => {
const {
Uint32Array,
Uint8Array,
} = window.__bootstrap.primordials;
const core = window.Deno.core;
const ops = core.ops;

const size = new Uint32Array(2);
function consoleSize(rid) {
return ops.op_console_size(rid);
ops.op_console_size(rid, size);
return { columns: size[0], rows: size[1] };
}

const isattyBuffer = new Uint8Array(1);
function isatty(rid) {
return ops.op_isatty(rid);
ops.op_isatty(rid, isattyBuffer);
return !!isattyBuffer[0];
}

const DEFAULT_SET_RAW_OPTIONS = {
cbreak: false,
};

const DEFAULT_CBREAK = false;
function setRaw(rid, mode, options = {}) {
const rOptions = { ...DEFAULT_SET_RAW_OPTIONS, ...options };
ops.op_set_raw({ rid, mode, options: rOptions });
ops.op_set_raw(rid, mode, options.cbreak || DEFAULT_CBREAK);
}

window.__bootstrap.tty = {
Expand Down
1 change: 0 additions & 1 deletion runtime/ops/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,7 +837,6 @@ fn op_copy_file_sync(

#[cfg(target_os = "macos")]
{
use libc::chmod;
use libc::clonefile;
use libc::stat;
use libc::unlink;
Expand Down
88 changes: 35 additions & 53 deletions runtime/ops/tty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@ use deno_core::error::AnyError;
use deno_core::op;
use deno_core::Extension;
use deno_core::OpState;
use deno_core::ResourceId;
use serde::Deserialize;
use serde::Serialize;
use std::io::Error;

#[cfg(unix)]
Expand Down Expand Up @@ -50,27 +47,15 @@ pub fn init() -> Extension {
.build()
}

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct SetRawOptions {
#[op(fast)]
fn op_set_raw(
state: &mut OpState,
rid: u32,
is_raw: bool,
cbreak: bool,
}

#[derive(Deserialize)]
pub struct SetRawArgs {
rid: ResourceId,
mode: bool,
options: SetRawOptions,
}

#[op]
fn op_set_raw(state: &mut OpState, args: SetRawArgs) -> Result<(), AnyError> {
) -> Result<(), AnyError> {
super::check_unstable(state, "Deno.setRaw");

let rid = args.rid;
let is_raw = args.mode;
let cbreak = args.options.cbreak;

// From https://github.com/kkawakam/rustyline/blob/master/src/tty/windows.rs
// and https://github.com/kkawakam/rustyline/blob/master/src/tty/unix.rs
// and https://github.com/crossterm-rs/crossterm/blob/e35d4d2c1cc4c919e36d242e014af75f6127ab50/src/terminal/sys/windows.rs
Expand Down Expand Up @@ -168,9 +153,13 @@ fn op_set_raw(state: &mut OpState, args: SetRawArgs) -> Result<(), AnyError> {
}
}

#[op]
fn op_isatty(state: &mut OpState, rid: ResourceId) -> Result<bool, AnyError> {
let isatty: bool = StdFileResource::with_file(state, rid, move |std_file| {
#[op(fast)]
fn op_isatty(
state: &mut OpState,
rid: u32,
out: &mut [u8],
) -> Result<(), AnyError> {
StdFileResource::with_file(state, rid, move |std_file| {
#[cfg(windows)]
{
use winapi::shared::minwindef::FALSE;
Expand All @@ -181,34 +170,34 @@ fn op_isatty(state: &mut OpState, rid: ResourceId) -> Result<bool, AnyError> {
// If I cannot get mode out of console, it is not a console.
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)]
Ok(unsafe { consoleapi::GetConsoleMode(handle, &mut test_mode) != FALSE })
{
out[0] = unsafe {
consoleapi::GetConsoleMode(handle, &mut test_mode) != FALSE
} as u8;
}
}
#[cfg(unix)]
{
use std::os::unix::io::AsRawFd;
let raw_fd = std_file.as_raw_fd();
// TODO(bartlomieju):
#[allow(clippy::undocumented_unsafe_blocks)]
Ok(unsafe { libc::isatty(raw_fd as libc::c_int) == 1 })
{
out[0] = unsafe { libc::isatty(raw_fd as libc::c_int) == 1 } as u8;
}
}
})?;
Ok(isatty)
}

#[derive(Serialize)]
struct ConsoleSize {
columns: u32,
rows: u32,
Ok(())
})
}

#[op]
#[op(fast)]
fn op_console_size(
state: &mut OpState,
rid: ResourceId,
) -> Result<ConsoleSize, AnyError> {
rid: u32,
result: &mut [u32],
) -> Result<(), AnyError> {
super::check_unstable(state, "Deno.consoleSize");

let size = StdFileResource::with_file(state, rid, move |std_file| {
StdFileResource::with_file(state, rid, move |std_file| {
#[cfg(windows)]
{
use std::os::windows::io::AsRawHandle;
Expand All @@ -224,11 +213,9 @@ fn op_console_size(
{
return Err(Error::last_os_error().into());
}

Ok(ConsoleSize {
columns: bufinfo.dwSize.X as u32,
rows: bufinfo.dwSize.Y as u32,
})
result[0] = bufinfo.dwSize.X as u32;
result[1] = bufinfo.dwSize.Y as u32;
Ok(())
}
}

Expand All @@ -244,15 +231,10 @@ fn op_console_size(
if libc::ioctl(fd, libc::TIOCGWINSZ, &mut size as *mut _) != 0 {
return Err(Error::last_os_error().into());
}

// TODO (caspervonb) return a tuple instead
Ok(ConsoleSize {
columns: size.ws_col as u32,
rows: size.ws_row as u32,
})
result[0] = size.ws_col as u32;
result[1] = size.ws_row as u32;
Ok(())
}
}
})?;

Ok(size)
})
}

0 comments on commit 72af149

Please sign in to comment.