perf: eliminate redundant allocations and computations (Sprint 1)
This commit applies eight low-risk internal optimizations identified
in the performance audit. No wire protocol changes — 100% MikroTik
compatible.
Changes:
- ecsrp5.rs: Cache WCurve in a global LazyLock, eliminating the
expensive BigUint modular square root recomputation on every
EC-SRP5 authentication. Also optimize the local hex::encode
module to use a single pre-allocated String instead of N format!
allocations.
- server.rs: Deduplicate Instant::now() calls in the TCP TX hot
loop, caching the result at the top of each iteration.
- csv_output.rs: Hold the CSV file handle open in a static
Mutex<Option<(String, File)>> instead of reopening the file on
every write_result call. Add explicit flush after each write.
- server_pro/user_db.rs: Replace hand-rolled Gregorian calendar
math (30+ lines looping from 1970) with chrono::Local::now().
Optimize hash_password() to write username:password directly
into the SHA256 hasher and hex-encode with a pre-allocated
String.
- server_pro/enforcer.rs: Replace allocating error string matching
(format!({}, e).as_str().contains(...)) with direct
QuotaError variant matching. Pass ip_str into flush_to_db()
to avoid a per-call ip.to_string().
- syslog_logger.rs: Move timestamp formatting outside the global
std::sync::Mutex to reduce lock hold time. Replace manual
calendar arithmetic with chrono::Local::now().format().
New dependency: chrono (already pulled in transitively by rusqlite).
This commit is contained in:
@@ -36,12 +36,12 @@ pub fn init(target: &str) -> std::io::Result<()> {
|
||||
/// Send a syslog message with the given severity and message.
|
||||
/// Severity: 6=info, 4=warning, 3=error
|
||||
fn send(severity: u8, msg: &str) {
|
||||
// Format timestamp outside the lock to minimize contention
|
||||
let priority = 128 + severity;
|
||||
let timestamp = bsd_timestamp();
|
||||
|
||||
let guard = SYSLOG.lock().unwrap();
|
||||
if let Some(ref sender) = *guard {
|
||||
// RFC 3164 (BSD syslog): <priority>Mon DD HH:MM:SS hostname program: message
|
||||
// facility=16 (local0) * 8 + severity
|
||||
let priority = 128 + severity;
|
||||
let timestamp = bsd_timestamp();
|
||||
let syslog_msg = format!(
|
||||
"<{}>{} {} btest-rs: {}",
|
||||
priority, timestamp, sender.hostname, msg,
|
||||
@@ -52,44 +52,7 @@ fn send(severity: u8, msg: &str) {
|
||||
|
||||
fn bsd_timestamp() -> String {
|
||||
// RFC 3164 format: "Mon DD HH:MM:SS" (no year)
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_secs();
|
||||
|
||||
// Simple conversion — good enough for syslog
|
||||
let secs_in_day = 86400u64;
|
||||
let days = now / secs_in_day;
|
||||
let time_of_day = now % secs_in_day;
|
||||
let hours = time_of_day / 3600;
|
||||
let minutes = (time_of_day % 3600) / 60;
|
||||
let seconds = time_of_day % 60;
|
||||
|
||||
// Day of year calculation (approximate months)
|
||||
let months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||
let days_in_months = [31u64,28,31,30,31,30,31,31,30,31,30,31];
|
||||
|
||||
// Days since epoch to year/month/day
|
||||
let mut y = 1970u64;
|
||||
let mut remaining = days;
|
||||
loop {
|
||||
let leap = if y % 4 == 0 && (y % 100 != 0 || y % 400 == 0) { 366 } else { 365 };
|
||||
if remaining < leap { break; }
|
||||
remaining -= leap;
|
||||
y += 1;
|
||||
}
|
||||
let leap = y % 4 == 0 && (y % 100 != 0 || y % 400 == 0);
|
||||
let mut m = 0usize;
|
||||
for i in 0..12 {
|
||||
let mut d = days_in_months[i];
|
||||
if i == 1 && leap { d += 1; }
|
||||
if remaining < d { m = i; break; }
|
||||
remaining -= d;
|
||||
}
|
||||
let day = remaining + 1;
|
||||
|
||||
format!("{} {:2} {:02}:{:02}:{:02}", months[m], day, hours, minutes, seconds)
|
||||
chrono::Local::now().format("%b %e %H:%M:%S").to_string()
|
||||
}
|
||||
|
||||
// --- Public logging functions ---
|
||||
|
||||
Reference in New Issue
Block a user