Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 59 additions & 9 deletions src/bin/ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,8 +1899,7 @@ impl App {
let custom_label = ui.add_sized(
[0.0, 0.0],
egui::Label::new(
egui::RichText::new("Custom SNI")
.color(egui::Color32::TRANSPARENT),
egui::RichText::new("Custom SNI").color(egui::Color32::TRANSPARENT),
),
);
ui.add(
Expand Down Expand Up @@ -1966,8 +1965,38 @@ fn fmt_bytes(b: u64) -> String {

// ---------- Background thread: owns the tokio runtime + proxy lifecycle ----------

const DESKTOP_RUNTIME_MIN_WORKERS: usize = 2;
const DESKTOP_RUNTIME_MAX_WORKERS: usize = 4;
const DESKTOP_RUNTIME_MAX_BLOCKING_THREADS: usize = 32;

fn desktop_runtime_worker_count(available_parallelism: usize) -> usize {
available_parallelism.clamp(DESKTOP_RUNTIME_MIN_WORKERS, DESKTOP_RUNTIME_MAX_WORKERS)
}

fn build_desktop_runtime() -> std::io::Result<(Runtime, usize)> {
let available = std::thread::available_parallelism()
.map(|n| n.get())
.unwrap_or(DESKTOP_RUNTIME_MIN_WORKERS);
let workers = desktop_runtime_worker_count(available);
let runtime = tokio::runtime::Builder::new_multi_thread()
.thread_name("mhrv-ui-worker")
.worker_threads(workers)
.max_blocking_threads(DESKTOP_RUNTIME_MAX_BLOCKING_THREADS)
.thread_keep_alive(Duration::from_secs(30))
.enable_all()
.build()?;
Ok((runtime, workers))
}

fn background_thread(shared: Arc<Shared>, rx: Receiver<Cmd>) {
let rt = Runtime::new().expect("failed to create tokio runtime");
let (rt, runtime_workers) = build_desktop_runtime().expect("failed to create tokio runtime");
push_log(
&shared,
&format!(
"[ui] tokio runtime ready: {} worker threads, {} max blocking threads",
runtime_workers, DESKTOP_RUNTIME_MAX_BLOCKING_THREADS
),
);

let mut active: Option<(
JoinHandle<()>,
Expand Down Expand Up @@ -2113,14 +2142,14 @@ fn background_thread(shared: Arc<Shared>, rx: Receiver<Cmd>) {
https://whatismyipaddress.com in your browser \
via 127.0.0.1:8085. The IP shown should be your \
tunnel-node's VPS IP. Tracking a real Full-mode \
test in #160."
test in #160.",
),
Some(mhrv_rs::config::Mode::Direct) => Some(
"Test Relay is wired only for apps_script mode. \
In direct mode there is no Apps Script relay — \
every request goes through the SNI-rewrite tunnel \
straight to Google's edge. Verify by loading \
https://www.google.com via the proxy."
https://www.google.com via the proxy.",
),
_ => None,
};
Expand Down Expand Up @@ -2492,10 +2521,7 @@ fn install_ui_tracing(shared: Arc<Shared>, config_level: &str) {
/// by `install_ui_tracing`. `apply_log_level` uses it to swap in a new
/// filter when the user clicks Save with a different log level (#401).
static LOG_RELOAD: std::sync::OnceLock<
tracing_subscriber::reload::Handle<
tracing_subscriber::EnvFilter,
tracing_subscriber::Registry,
>,
tracing_subscriber::reload::Handle<tracing_subscriber::EnvFilter, tracing_subscriber::Registry>,
> = std::sync::OnceLock::new();

/// Reinstall the tracing filter at runtime. Called from the Save handler
Expand Down Expand Up @@ -2568,3 +2594,27 @@ fn push_log(shared: &Shared, msg: &str) {
s.log.pop_front();
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn desktop_runtime_worker_count_clamps_small_devices_to_two_workers() {
assert_eq!(desktop_runtime_worker_count(0), 2);
assert_eq!(desktop_runtime_worker_count(1), 2);
assert_eq!(desktop_runtime_worker_count(2), 2);
}

#[test]
fn desktop_runtime_worker_count_uses_midrange_core_counts_directly() {
assert_eq!(desktop_runtime_worker_count(3), 3);
assert_eq!(desktop_runtime_worker_count(4), 4);
}

#[test]
fn desktop_runtime_worker_count_caps_large_desktops_at_four_workers() {
assert_eq!(desktop_runtime_worker_count(8), 4);
assert_eq!(desktop_runtime_worker_count(32), 4);
}
}
Loading