Skip to content
Merged
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ data class MhrvConfig(
val verifySsl: Boolean = true,
val logLevel: String = "info",
val parallelRelay: Int = 1,
val coalesceStepMs: Int = 40,
val coalesceStepMs: Int = 10,
val coalesceMaxMs: Int = 1000,
val upstreamSocks5: String = "",

Expand Down Expand Up @@ -210,7 +210,7 @@ data class MhrvConfig(
put("verify_ssl", verifySsl)
put("log_level", logLevel)
put("parallel_relay", parallelRelay)
if (coalesceStepMs != 40) put("coalesce_step_ms", coalesceStepMs)
if (coalesceStepMs != 10) put("coalesce_step_ms", coalesceStepMs)
if (coalesceMaxMs != 1000) put("coalesce_max_ms", coalesceMaxMs)
if (upstreamSocks5.isNotBlank()) {
put("upstream_socks5", upstreamSocks5.trim())
Expand Down Expand Up @@ -422,7 +422,7 @@ object ConfigStore {
verifySsl = obj.optBoolean("verify_ssl", true),
logLevel = obj.optString("log_level", "info"),
parallelRelay = obj.optInt("parallel_relay", 1),
coalesceStepMs = obj.optInt("coalesce_step_ms", 40),
coalesceStepMs = obj.optInt("coalesce_step_ms", 10),
coalesceMaxMs = obj.optInt("coalesce_max_ms", 1000),
upstreamSocks5 = obj.optString("upstream_socks5", ""),
passthroughHosts = obj.optJSONArray("passthrough_hosts")?.let { arr ->
Expand Down
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub struct Config {
pub parallel_relay: u8,
/// Adaptive batch coalesce: after each op arrives, wait this many ms
/// for more ops before firing the batch. Resets on every arrival.
/// 0 = use compiled default (40ms).
/// 0 = use compiled default (10ms).
#[serde(default)]
pub coalesce_step_ms: u16,
/// Hard cap on total coalesce wait (ms). 0 = use compiled default (1000ms).
Expand Down
2 changes: 1 addition & 1 deletion src/proxy_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ impl ProxyServer {
mitm,
rewrite_ctx,
tunnel_mux: None, // initialized in run() inside the tokio runtime
coalesce_step_ms: if config.coalesce_step_ms > 0 { config.coalesce_step_ms as u64 } else { 40 },
coalesce_step_ms: if config.coalesce_step_ms > 0 { config.coalesce_step_ms as u64 } else { 10 },
coalesce_max_ms: if config.coalesce_max_ms > 0 { config.coalesce_max_ms as u64 } else { 1000 },
})
}
Expand Down
13 changes: 12 additions & 1 deletion src/tunnel_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,18 @@ const CLIENT_FIRST_DATA_WAIT: Duration = Duration::from_millis(50);
/// Adaptive coalesce defaults: after each new op arrives, wait another
/// step for more ops. Resets on every arrival, up to max from the first
/// op. Overridable via config `coalesce_step_ms` / `coalesce_max_ms`.
const DEFAULT_COALESCE_STEP_MS: u64 = 40;
///
/// 10 ms is enough to catch ops that arrive in the same event-loop tick
/// (e.g. a browser opening 6 parallel connections) without adding
/// perceptible latency to downloads where the tunnel-node reply — not
/// coalescing — is the real bottleneck. When both sides *do* have data
/// in flight (uploads, bursty page loads), the adaptive reset still
/// packs batches efficiently: each arriving op resets the step timer, so
/// a rapid burst naturally coalesces up to `DEFAULT_COALESCE_MAX_MS`
/// without an explicit upload/download distinction. The net effect is
/// "don't wait when there's nothing to wait for; batch aggressively when
/// there is."
const DEFAULT_COALESCE_STEP_MS: u64 = 10;
const DEFAULT_COALESCE_MAX_MS: u64 = 1000;

/// Structured error code the tunnel-node returns when it doesn't know the
Expand Down
4 changes: 2 additions & 2 deletions tunnel-node/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ const ACTIVE_DRAIN_DEADLINE: Duration = Duration::from_millis(350);
/// still arriving. Stops when no new data arrived in the last STEP (the
/// burst is over) or MAX is reached. Packing more session responses into
/// one batch saves quota on high-latency relays (~1.5s Apps Script overhead).
const STRAGGLER_SETTLE_STEP: Duration = Duration::from_millis(40);
const STRAGGLER_SETTLE_MAX: Duration = Duration::from_millis(500);
const STRAGGLER_SETTLE_STEP: Duration = Duration::from_millis(10);
const STRAGGLER_SETTLE_MAX: Duration = Duration::from_millis(1000);

/// Drain-phase deadline when the batch is a pure poll (no writes, no new
/// connections — clients just asking "any push data?"). Holding the
Expand Down
Loading