From 168eb8e01d3cdbd6358e11cf399fbf4ef1db358b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Fri, 9 Jun 2023 13:52:51 +0200 Subject: [PATCH] perf: add Tokio runtime monitor (#19415) This commit adds ability to print metrics of the Tokio runtime to the console by passing "DENO_TOKIO_METRICS=1" env var. Metrics will be printed every second, but this can be changed by "DENO_TOKIO_METRICS_INTERVAL=500" env var. --- .cargo/config.toml | 2 ++ .github/workflows/ci.generate.ts | 3 +- .github/workflows/ci.yml | 7 +++-- Cargo.lock | 13 +++++++++ Cargo.toml | 1 + cli/main.rs | 5 ++-- runtime/Cargo.toml | 1 + runtime/tokio_util.rs | 49 ++++++++++++++++++++++++++++++-- 8 files changed, 73 insertions(+), 8 deletions(-) diff --git a/.cargo/config.toml b/.cargo/config.toml index 10e4b295cc..ed50de0847 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -23,4 +23,6 @@ rustflags = [ "clippy::missing_safety_doc", "-D", "clippy::undocumented_unsafe_blocks", + "--cfg", + "tokio_unstable", ] diff --git a/.github/workflows/ci.generate.ts b/.github/workflows/ci.generate.ts index 6b1089e036..e6a5b12896 100755 --- a/.github/workflows/ci.generate.ts +++ b/.github/workflows/ci.generate.ts @@ -5,7 +5,7 @@ import * as yaml from "https://deno.land/std@0.173.0/encoding/yaml.ts"; // Bump this number when you want to purge the cache. // Note: the tools/release/01_bump_crate_versions.ts script will update this version // automatically via regex, so ensure that this line maintains this format. -const cacheVersion = 37; +const cacheVersion = 38; const Runners = (() => { const ubuntuRunner = "ubuntu-22.04"; @@ -85,6 +85,7 @@ RUSTFLAGS<<__1 -C link-arg=-Wl,--allow-shlib-undefined -C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache -C link-arg=-Wl,--thinlto-cache-policy,cache_size_bytes=700m + --cfg tokio_unstable \${{ env.RUSTFLAGS }} __1 RUSTDOCFLAGS<<__1 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 00660ea6ed..e631544179 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -260,6 +260,7 @@ jobs: -C link-arg=-Wl,--allow-shlib-undefined -C link-arg=-Wl,--thinlto-cache-dir=$(pwd)/target/release/lto-cache -C link-arg=-Wl,--thinlto-cache-policy,cache_size_bytes=700m + --cfg tokio_unstable ${{ env.RUSTFLAGS }} __1 RUSTDOCFLAGS<<__1 @@ -298,7 +299,7 @@ jobs: ~/.cargo/registry/index ~/.cargo/registry/cache ~/.cargo/git/db - key: '37-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}' + key: '38-cargo-home-${{ matrix.os }}-${{ hashFiles(''Cargo.lock'') }}' if: '!(github.event_name == ''pull_request'' && matrix.skip_pr)' - name: Restore cache build output (PR) uses: actions/cache/restore@v3 @@ -310,7 +311,7 @@ jobs: !./target/*/*.zip !./target/*/*.tar.gz key: never_saved - restore-keys: '37-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-' + restore-keys: '38-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-' - name: Apply and update mtime cache if: '!(github.event_name == ''pull_request'' && matrix.skip_pr) && (!startsWith(github.ref, ''refs/tags/''))' uses: ./.github/mtime_cache @@ -600,7 +601,7 @@ jobs: !./target/*/gn_out !./target/*/*.zip !./target/*/*.tar.gz - key: '37-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' + key: '38-cargo-target-${{ matrix.os }}-${{ matrix.profile }}-${{ matrix.job }}-${{ github.sha }}' publish-canary: name: publish canary runs-on: ubuntu-22.04 diff --git a/Cargo.lock b/Cargo.lock index c18e1a5032..9593dafa4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1315,6 +1315,7 @@ dependencies = [ "termcolor", "test_util", "tokio", + "tokio-metrics", "uuid", "winapi", "winres", @@ -5249,6 +5250,18 @@ dependencies = [ "syn 2.0.13", ] +[[package]] +name = "tokio-metrics" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b60ac6224d622f71d0b80546558eedf8ff6c2d3817517a9d3ed87ce24fccf6a6" +dependencies = [ + "futures-util", + "pin-project-lite", + "tokio", + "tokio-stream", +] + [[package]] name = "tokio-rustls" version = "0.24.0" diff --git a/Cargo.toml b/Cargo.toml index 86b2518ad4..47a416d2e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -135,6 +135,7 @@ tar = "=0.4.38" tempfile = "3.4.0" thiserror = "1.0.40" tokio = { version = "1.28.1", features = ["full"] } +tokio-metrics = { version = "0.2.2", features = ["rt"] } tokio-rustls = "0.24.0" tokio-util = "0.7.4" tower-lsp = { version = "=0.17.0", features = ["proposed"] } diff --git a/cli/main.rs b/cli/main.rs index 73820cb931..27dd4bcd8b 100644 --- a/cli/main.rs +++ b/cli/main.rs @@ -41,7 +41,7 @@ use deno_core::futures::FutureExt; use deno_core::task::JoinHandle; use deno_runtime::colors; use deno_runtime::fmt_errors::format_js_error; -use deno_runtime::tokio_util::create_and_run_current_thread; +use deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics; use factory::CliFactory; use std::env; use std::env::current_exe; @@ -308,7 +308,8 @@ pub fn main() { run_subcommand(flags).await }; - let exit_code = unwrap_or_exit(create_and_run_current_thread(future)); + let exit_code = + unwrap_or_exit(create_and_run_current_thread_with_maybe_metrics(future)); std::process::exit(exit_code); } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 3e7e57141a..77571b2102 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -105,6 +105,7 @@ serde.workspace = true signal-hook-registry = "1.4.0" termcolor = "1.1.3" tokio.workspace = true +tokio-metrics.workspace = true uuid.workspace = true [target.'cfg(windows)'.dependencies] diff --git a/runtime/tokio_util.rs b/runtime/tokio_util.rs index 1245a5b8eb..204b928f43 100644 --- a/runtime/tokio_util.rs +++ b/runtime/tokio_util.rs @@ -3,6 +3,7 @@ use std::fmt::Debug; use std::str::FromStr; use deno_core::task::MaskFutureAsSend; +use tokio_metrics::RuntimeMonitor; /// Default configuration for tokio. In the future, this method may have different defaults /// depending on the platform and/or CPU layout. @@ -47,7 +48,10 @@ pub fn create_basic_runtime() -> tokio::runtime::Runtime { } #[inline(always)] -pub fn create_and_run_current_thread(future: F) -> R +fn create_and_run_current_thread_inner( + future: F, + metrics_enabled: bool, +) -> R where F: std::future::Future + 'static, R: Send + 'static, @@ -66,6 +70,47 @@ where // SAFETY: this this is guaranteed to be running on a current-thread executor let future = unsafe { MaskFutureAsSend::new(future) }; - let join_handle = rt.spawn(future); + let join_handle = if metrics_enabled { + rt.spawn(async move { + let metrics_interval: u64 = std::env::var("DENO_TOKIO_METRICS_INTERVAL") + .ok() + .and_then(|val| val.parse().ok()) + .unwrap_or(1000); + let handle = tokio::runtime::Handle::current(); + let runtime_monitor = RuntimeMonitor::new(&handle); + tokio::spawn(async move { + for interval in runtime_monitor.intervals() { + println!("{:#?}", interval); + // wait 500ms + tokio::time::sleep(std::time::Duration::from_millis( + metrics_interval, + )) + .await; + } + }); + future.await + }) + } else { + rt.spawn(future) + }; rt.block_on(join_handle).unwrap().into_inner() } + +#[inline(always)] +pub fn create_and_run_current_thread(future: F) -> R +where + F: std::future::Future + 'static, + R: Send + 'static, +{ + create_and_run_current_thread_inner(future, false) +} + +#[inline(always)] +pub fn create_and_run_current_thread_with_maybe_metrics(future: F) -> R +where + F: std::future::Future + 'static, + R: Send + 'static, +{ + let metrics_enabled = std::env::var("DENO_TOKIO_METRICS").ok().is_some(); + create_and_run_current_thread_inner(future, metrics_enabled) +}