Skip to content

Commit 3c5272d

Browse files
committed
chore: bump version to 145.0.1 and add RUSTY_V8_REUSE_PREBUILT
- Bump version from 145.0.0 to 145.0.1 - Add RUSTY_V8_REUSE_PREBUILT env var to skip downloading prebuilt binaries when they already exist locally. This is useful when only Rust code changed but V8 itself hasn't changed (e.g., version bump without V8 update).
1 parent 30026aa commit 3c5272d

6 files changed

Lines changed: 178 additions & 103 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "openworkers-v8"
3-
version = "145.0.0"
3+
version = "145.0.1"
44
description = "Rust bindings to V8 (fork with Locker/UnenteredIsolate support for isolate pooling)"
55
readme = "README.md"
66
authors = ["the Deno authors", "OpenWorkers Authors <contact@openworkers.dev>"]

benches/mutex_comparison.rs

Lines changed: 130 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -9,117 +9,149 @@ const ITERATIONS: u64 = 10_000_000;
99
const THREAD_COUNTS: &[usize] = &[2, 4, 8, 16];
1010

1111
fn bench_std_mutex_uncontended() -> Duration {
12-
let mutex = std::sync::Mutex::new(0u64);
13-
let start = Instant::now();
14-
for _ in 0..ITERATIONS {
15-
let mut guard = mutex.lock().unwrap();
16-
*guard += 1;
17-
}
18-
start.elapsed()
12+
let mutex = std::sync::Mutex::new(0u64);
13+
let start = Instant::now();
14+
for _ in 0..ITERATIONS {
15+
let mut guard = mutex.lock().unwrap();
16+
*guard += 1;
17+
}
18+
start.elapsed()
1919
}
2020

2121
fn bench_parking_lot_uncontended() -> Duration {
22-
let mutex = parking_lot::Mutex::new(0u64);
23-
let start = Instant::now();
24-
for _ in 0..ITERATIONS {
25-
let mut guard = mutex.lock();
26-
*guard += 1;
27-
}
28-
start.elapsed()
22+
let mutex = parking_lot::Mutex::new(0u64);
23+
let start = Instant::now();
24+
for _ in 0..ITERATIONS {
25+
let mut guard = mutex.lock();
26+
*guard += 1;
27+
}
28+
start.elapsed()
2929
}
3030

3131
fn bench_std_mutex_contended(threads: usize) -> Duration {
32-
let mutex = Arc::new(std::sync::Mutex::new(0u64));
33-
let start = Instant::now();
34-
35-
let handles: Vec<_> = (0..threads)
36-
.map(|_| {
37-
let mutex = Arc::clone(&mutex);
38-
thread::spawn(move || {
39-
for _ in 0..(ITERATIONS / threads as u64) {
40-
let mut guard = mutex.lock().unwrap();
41-
*guard += 1;
42-
}
43-
})
44-
})
45-
.collect();
46-
47-
for handle in handles {
48-
handle.join().unwrap();
49-
}
50-
start.elapsed()
32+
let mutex = Arc::new(std::sync::Mutex::new(0u64));
33+
let start = Instant::now();
34+
35+
let handles: Vec<_> = (0..threads)
36+
.map(|_| {
37+
let mutex = Arc::clone(&mutex);
38+
thread::spawn(move || {
39+
for _ in 0..(ITERATIONS / threads as u64) {
40+
let mut guard = mutex.lock().unwrap();
41+
*guard += 1;
42+
}
43+
})
44+
})
45+
.collect();
46+
47+
for handle in handles {
48+
handle.join().unwrap();
49+
}
50+
start.elapsed()
5151
}
5252

5353
fn bench_parking_lot_contended(threads: usize) -> Duration {
54-
let mutex = Arc::new(parking_lot::Mutex::new(0u64));
55-
let start = Instant::now();
56-
57-
let handles: Vec<_> = (0..threads)
58-
.map(|_| {
59-
let mutex = Arc::clone(&mutex);
60-
thread::spawn(move || {
61-
for _ in 0..(ITERATIONS / threads as u64) {
62-
let mut guard = mutex.lock();
63-
*guard += 1;
64-
}
65-
})
66-
})
67-
.collect();
68-
69-
for handle in handles {
70-
handle.join().unwrap();
71-
}
72-
start.elapsed()
54+
let mutex = Arc::new(parking_lot::Mutex::new(0u64));
55+
let start = Instant::now();
56+
57+
let handles: Vec<_> = (0..threads)
58+
.map(|_| {
59+
let mutex = Arc::clone(&mutex);
60+
thread::spawn(move || {
61+
for _ in 0..(ITERATIONS / threads as u64) {
62+
let mut guard = mutex.lock();
63+
*guard += 1;
64+
}
65+
})
66+
})
67+
.collect();
68+
69+
for handle in handles {
70+
handle.join().unwrap();
71+
}
72+
start.elapsed()
7373
}
7474

7575
fn format_results(name: &str, std_time: Duration, pl_time: Duration) {
76-
let std_ns = std_time.as_nanos() as f64 / ITERATIONS as f64;
77-
let pl_ns = pl_time.as_nanos() as f64 / ITERATIONS as f64;
78-
let speedup = std_time.as_nanos() as f64 / pl_time.as_nanos() as f64;
79-
80-
println!("\n{name}:");
81-
println!(" std::sync::Mutex: {std_ns:.2} ns/op");
82-
println!(" parking_lot::Mutex: {pl_ns:.2} ns/op");
83-
println!(" Speedup: {speedup:.2}x");
76+
let std_ns = std_time.as_nanos() as f64 / ITERATIONS as f64;
77+
let pl_ns = pl_time.as_nanos() as f64 / ITERATIONS as f64;
78+
let speedup = std_time.as_nanos() as f64 / pl_time.as_nanos() as f64;
79+
80+
println!("\n{name}:");
81+
println!(" std::sync::Mutex: {std_ns:.2} ns/op");
82+
println!(" parking_lot::Mutex: {pl_ns:.2} ns/op");
83+
println!(" Speedup: {speedup:.2}x");
8484
}
8585

8686
fn main() {
87-
println!("Mutex Benchmark Comparison");
88-
println!("==========================");
89-
println!("Iterations: {ITERATIONS}");
90-
91-
// Size comparison (important: empty mutex size)
92-
println!("\nSize comparison:");
93-
println!(" std::sync::Mutex<()>: {} bytes", std::mem::size_of::<std::sync::Mutex<()>>());
94-
println!(" parking_lot::Mutex<()>: {} bytes", std::mem::size_of::<parking_lot::Mutex<()>>());
95-
println!(" std::sync::Mutex<u64>: {} bytes", std::mem::size_of::<std::sync::Mutex<u64>>());
96-
println!(" parking_lot::Mutex<u64>: {} bytes", std::mem::size_of::<parking_lot::Mutex<u64>>());
97-
98-
// Warmup
99-
let _ = bench_std_mutex_uncontended();
100-
let _ = bench_parking_lot_uncontended();
101-
102-
// Uncontended benchmarks (run 3 times, take best)
103-
println!("\nRunning uncontended benchmarks (best of 3)...");
104-
let std_uncontended = (0..3).map(|_| bench_std_mutex_uncontended()).min().unwrap();
105-
let pl_uncontended = (0..3).map(|_| bench_parking_lot_uncontended()).min().unwrap();
106-
format_results("Uncontended (single thread)", std_uncontended, pl_uncontended);
107-
108-
// Contended benchmarks with different thread counts
109-
println!("\nRunning contended benchmarks...");
110-
for &threads in THREAD_COUNTS {
111-
let std_contended = bench_std_mutex_contended(threads);
112-
let pl_contended = bench_parking_lot_contended(threads);
113-
format_results(&format!("Contended ({threads} threads)"), std_contended, pl_contended);
114-
}
115-
116-
println!("\n=== Summary ===");
117-
println!("parking_lot::Mutex advantages:");
118-
println!(" - No poisoning (panic safety - if one thread panics, others continue)");
119-
println!(" - Cleaner API (no .unwrap() needed after .lock())");
120-
println!(" - 8x smaller for Mutex<()>: 1 byte vs 8 bytes");
121-
println!(" - Better performance under low-to-moderate contention (2-4 threads)");
122-
println!();
123-
println!("Note: std::sync::Mutex may perform better under very high contention");
124-
println!(" (8+ threads), but rusty_v8 usage patterns are low contention.");
87+
println!("Mutex Benchmark Comparison");
88+
println!("==========================");
89+
println!("Iterations: {ITERATIONS}");
90+
91+
// Size comparison (important: empty mutex size)
92+
println!("\nSize comparison:");
93+
println!(
94+
" std::sync::Mutex<()>: {} bytes",
95+
std::mem::size_of::<std::sync::Mutex<()>>()
96+
);
97+
println!(
98+
" parking_lot::Mutex<()>: {} bytes",
99+
std::mem::size_of::<parking_lot::Mutex<()>>()
100+
);
101+
println!(
102+
" std::sync::Mutex<u64>: {} bytes",
103+
std::mem::size_of::<std::sync::Mutex<u64>>()
104+
);
105+
println!(
106+
" parking_lot::Mutex<u64>: {} bytes",
107+
std::mem::size_of::<parking_lot::Mutex<u64>>()
108+
);
109+
110+
// Warmup
111+
let _ = bench_std_mutex_uncontended();
112+
let _ = bench_parking_lot_uncontended();
113+
114+
// Uncontended benchmarks (run 3 times, take best)
115+
println!("\nRunning uncontended benchmarks (best of 3)...");
116+
let std_uncontended =
117+
(0..3).map(|_| bench_std_mutex_uncontended()).min().unwrap();
118+
let pl_uncontended = (0..3)
119+
.map(|_| bench_parking_lot_uncontended())
120+
.min()
121+
.unwrap();
122+
format_results(
123+
"Uncontended (single thread)",
124+
std_uncontended,
125+
pl_uncontended,
126+
);
127+
128+
// Contended benchmarks with different thread counts
129+
println!("\nRunning contended benchmarks...");
130+
for &threads in THREAD_COUNTS {
131+
let std_contended = bench_std_mutex_contended(threads);
132+
let pl_contended = bench_parking_lot_contended(threads);
133+
format_results(
134+
&format!("Contended ({threads} threads)"),
135+
std_contended,
136+
pl_contended,
137+
);
138+
}
139+
140+
println!("\n=== Summary ===");
141+
println!("parking_lot::Mutex advantages:");
142+
println!(
143+
" - No poisoning (panic safety - if one thread panics, others continue)"
144+
);
145+
println!(" - Cleaner API (no .unwrap() needed after .lock())");
146+
println!(" - 8x smaller for Mutex<()>: 1 byte vs 8 bytes");
147+
println!(
148+
" - Better performance under low-to-moderate contention (2-4 threads)"
149+
);
150+
println!();
151+
println!(
152+
"Note: std::sync::Mutex may perform better under very high contention"
153+
);
154+
println!(
155+
" (8+ threads), but rusty_v8 usage patterns are low contention."
156+
);
125157
}

build.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ fn main() {
4040
"OUT_DIR",
4141
"RUSTY_V8_ARCHIVE",
4242
"RUSTY_V8_MIRROR",
43+
"RUSTY_V8_REUSE_PREBUILT",
4344
"RUSTY_V8_SRC_BINDING_PATH",
4445
"SCCACHE",
4546
"V8_FORCE_DEBUG",
@@ -720,7 +721,20 @@ fn download_static_lib_binaries() {
720721
fs::create_dir_all(&dir).unwrap();
721722
println!("cargo:rustc-link-search={}", dir.display());
722723

723-
download_file(&url, &static_lib_path());
724+
let lib_path = static_lib_path();
725+
726+
// If RUSTY_V8_REUSE_PREBUILT is set and the library already exists,
727+
// skip the download. This is useful when only Rust code changed but
728+
// V8 itself hasn't changed (e.g., version bump without V8 update).
729+
if env::var("RUSTY_V8_REUSE_PREBUILT").is_ok() && lib_path.exists() {
730+
println!(
731+
"cargo:warning=Reusing existing prebuilt V8 library at {}",
732+
lib_path.display()
733+
);
734+
return;
735+
}
736+
737+
download_file(&url, &lib_path);
724738
}
725739

726740
fn decompress_to_writer<R, W>(input: &mut R, output: &mut W) -> io::Result<()>
@@ -869,6 +883,35 @@ fn print_prebuilt_src_binding_path() {
869883
.unwrap_or_else(|_| get_dirs().root.join("gen"));
870884
let src_binding_path = out_dir.join(name.clone());
871885

886+
// If RUSTY_V8_REUSE_PREBUILT is set, look for any existing binding file
887+
// in the gen directory (ignoring version in path).
888+
if env::var("RUSTY_V8_REUSE_PREBUILT").is_ok() {
889+
let gen_dir = get_dirs().root.join("gen");
890+
if let Ok(entries) = fs::read_dir(&gen_dir) {
891+
for entry in entries.flatten() {
892+
let path = entry.path();
893+
if let Some(filename) = path.file_name().and_then(|f| f.to_str()) {
894+
// Match pattern: src_binding{features}_{profile}_{target}.rs
895+
if filename.starts_with("src_binding")
896+
&& filename.ends_with(".rs")
897+
&& filename.contains(&format!("_{profile}_"))
898+
&& filename.contains(&target)
899+
{
900+
println!(
901+
"cargo:warning=Reusing existing binding file at {}",
902+
path.display()
903+
);
904+
println!(
905+
"cargo:rustc-env=RUSTY_V8_SRC_BINDING_PATH={}",
906+
path.display()
907+
);
908+
return;
909+
}
910+
}
911+
}
912+
}
913+
}
914+
872915
if !src_binding_path.exists() {
873916
fs::create_dir_all(&out_dir).unwrap();
874917
let default_base =

src/V8.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
2+
use parking_lot::Mutex;
23
use std::ffi::CStr;
34
use std::ffi::CString;
4-
use parking_lot::Mutex;
55
use std::vec::Vec;
66

77
use crate::platform::Platform;

tests/test_api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
2+
use parking_lot::Mutex;
23
use std::any::type_name;
34
use std::borrow::Cow;
45
use std::cell::RefCell;
@@ -15,7 +16,6 @@ use std::ptr::addr_of_mut;
1516
use std::rc::Rc;
1617
use std::sync::Arc;
1718
use std::sync::LazyLock;
18-
use parking_lot::Mutex;
1919
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
2020
use v8::AccessorConfiguration;
2121
use v8::fast_api;

0 commit comments

Comments
 (0)