diff --git a/cvm-rs/Cargo.lock b/cvm-rs/Cargo.lock index be20b1b..1bdf8c0 100644 --- a/cvm-rs/Cargo.lock +++ b/cvm-rs/Cargo.lock @@ -2,42 +2,12 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "addr2line" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "anyhow" version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" -[[package]] -name = "backtrace" -version = "0.3.73" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - [[package]] name = "cc" version = "1.0.99" @@ -59,6 +29,31 @@ dependencies = [ "cc", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "cvm-rs" version = "0.1.1" @@ -66,10 +61,16 @@ dependencies = [ "libc", "neon", "once_cell", - "tokio", + "rayon", "turbojpeg-sys", ] +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + [[package]] name = "getrandom" version = "0.2.15" @@ -81,18 +82,6 @@ dependencies = [ "wasi", ] -[[package]] -name = "gimli" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" - -[[package]] -name = "hermit-abi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" - [[package]] name = "libc" version = "0.2.155" @@ -109,21 +98,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "neon" version = "1.0.0" @@ -150,37 +124,12 @@ dependencies = [ "syn-mid", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.36.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "pin-project-lite" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" - [[package]] name = "pkg-config" version = "0.3.30" @@ -206,10 +155,24 @@ dependencies = [ ] [[package]] -name = "rustc-demangle" -version = "0.1.24" +name = "rayon" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] [[package]] name = "semver" @@ -251,17 +214,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tokio" -version = "1.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" -dependencies = [ - "backtrace", - "num_cpus", - "pin-project-lite", -] - [[package]] name = "turbojpeg-sys" version = "1.0.0" diff --git a/cvm-rs/Cargo.toml b/cvm-rs/Cargo.toml index 849a736..8ad26c2 100644 --- a/cvm-rs/Cargo.toml +++ b/cvm-rs/Cargo.toml @@ -14,5 +14,5 @@ libc = "0.2.155" # Required for JPEG once_cell = "1.19.0" -tokio = { version = "1.38.0", features = [ "rt", "rt-multi-thread" ] } turbojpeg-sys = "1.0.0" +rayon = "1.10.0" diff --git a/cvm-rs/src/jpeg_js.rs b/cvm-rs/src/jpeg_js.rs index e13b557..8aac0b5 100644 --- a/cvm-rs/src/jpeg_js.rs +++ b/cvm-rs/src/jpeg_js.rs @@ -4,19 +4,30 @@ use neon::prelude::*; use neon::types::buffer::TypedArray; use once_cell::sync::OnceCell; -use tokio::runtime::Runtime; use std::cell::RefCell; +use rayon::{ThreadPool, ThreadPoolBuilder}; + use crate::jpeg_compressor::*; -/// Gives a static Tokio runtime. We should replace this with -/// rayon or something, but for now tokio works. -fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> { - static RUNTIME: OnceCell = OnceCell::new(); +/// Gives a Rayon thread pool we use for parallelism +fn rayon_pool<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static ThreadPool> { + static RUNTIME: OnceCell = OnceCell::new(); RUNTIME - .get_or_try_init(Runtime::new) + .get_or_try_init(|| { + // spawn at least 4 threads + let mut nr_threads = std::thread::available_parallelism().expect("??").get() / 8; + if nr_threads == 0 { + nr_threads = 4; + } + + ThreadPoolBuilder::new() + .num_threads(nr_threads) + .thread_name(|index| format!("cvmrs_jpeg_{}", index + 1)) + .build() + }) .or_else(|err| cx.throw_error(&err.to_string())) } @@ -24,6 +35,9 @@ thread_local! { static COMPRESSOR: RefCell = RefCell::new(JpegCompressor::new()); } +// TODO: We should probably allow passing an array of images to encode, which would +// increase parallelism heavily. + fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise> { let input = cx.argument::(0)?; @@ -35,7 +49,7 @@ fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise> let (deferred, promise) = cx.promise(); let channel = cx.channel(); - let runtime = runtime(cx)?; + let pool = rayon_pool(cx)?; let buf = buffer.as_slice(cx); @@ -49,8 +63,9 @@ fn jpeg_encode_impl<'a>(cx: &mut FunctionContext<'a>) -> JsResult<'a, JsPromise> locked.copy_from_slice(buf); } - // Spawn off a tokio blocking pool thread that will do the work for us - runtime.spawn_blocking(move || { + // Spawn a task on the rayon pool that encodes the JPEG and fufills the promise + // once it is done encoding. + pool.spawn_fifo(move || { let clone = Arc::clone(©); let locked = clone.lock().unwrap();