v0.35.1: performance, AGPL licensing and documentation overhaul
- Web Server reads static files inline; proxy middleware chain flattened - About window with license summary and project links; AGPL-3.0-or-later - Rewritten documentation: feature list, screenshots, performance guide - Fix false spikes in per-Vhost request-rate charts
This commit is contained in:
1 parent
d3b492874b
commit
eba9f89283
135 files changed
+1425
-1064
No files matched your search
+35
-13
@@ -9,7 +9,8 @@ use std::{
|
||||
use tokio::sync::mpsc;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
const QUEUE_CAPACITY: usize = 2048;
|
||||
const QUEUE_CAPACITY: usize = 8192;
|
||||
const DRAIN_INTERVAL: std::time::Duration = std::time::Duration::from_millis(50);
|
||||
const TOP_CAPACITY: usize = 32;
|
||||
const MAX_VHOSTS: usize = 64;
|
||||
const MAX_LABEL_BYTES: usize = 256;
|
||||
@@ -228,22 +229,43 @@ impl Analytics {
|
||||
let (tx, mut rx) = mpsc::channel::<Sample>(QUEUE_CAPACITY);
|
||||
let worker_state = state.clone();
|
||||
tokio::spawn(async move {
|
||||
let mut batch = Vec::with_capacity(64);
|
||||
// Drain on a short interval instead of waking once per request.
|
||||
let mut tick = tokio::time::interval(DRAIN_INTERVAL);
|
||||
tick.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Delay);
|
||||
let mut batch = Vec::with_capacity(256);
|
||||
loop {
|
||||
tokio::select! {
|
||||
_ = shutdown.cancelled() => break,
|
||||
count = rx.recv_many(&mut batch, 64) => {
|
||||
if count == 0 { break; }
|
||||
let mut state = worker_state.lock().unwrap_or_else(|e| e.into_inner());
|
||||
for sample in batch.drain(..) {
|
||||
if let Some(counters) = state.vhosts.get_mut(sample.vhost.as_str()) {
|
||||
counters.record(sample);
|
||||
} else if state.vhosts.len() < MAX_VHOSTS {
|
||||
let name = sample.vhost.clone();
|
||||
let mut counters = Counters::default();
|
||||
counters.record(sample);
|
||||
state.vhosts.insert(name, counters);
|
||||
_ = tick.tick() => {
|
||||
let mut closed = false;
|
||||
loop {
|
||||
while batch.len() < 256 {
|
||||
match rx.try_recv() {
|
||||
Ok(sample) => batch.push(sample),
|
||||
Err(mpsc::error::TryRecvError::Empty) => break,
|
||||
Err(mpsc::error::TryRecvError::Disconnected) => {
|
||||
closed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if batch.is_empty() {
|
||||
break;
|
||||
}
|
||||
let mut state = worker_state.lock().unwrap_or_else(|e| e.into_inner());
|
||||
for sample in batch.drain(..) {
|
||||
if let Some(counters) = state.vhosts.get_mut(sample.vhost.as_str()) {
|
||||
counters.record(sample);
|
||||
} else if state.vhosts.len() < MAX_VHOSTS {
|
||||
let name = sample.vhost.clone();
|
||||
let mut counters = Counters::default();
|
||||
counters.record(sample);
|
||||
state.vhosts.insert(name, counters);
|
||||
}
|
||||
}
|
||||
}
|
||||
if closed {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user