From c5bbacd3948e81da11d1d336214d6a63ccd3c436 Mon Sep 17 00:00:00 2001 From: monosans Date: Wed, 24 Dec 2025 13:49:42 +0300 Subject: [PATCH] perf: reduce string allocations --- src/output.rs | 17 ++++++++++++----- src/proxy.rs | 14 ++++++++++---- src/raw_config.rs | 26 +++++++++++++++++++------- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/output.rs b/src/output.rs index ba20b40..f2a2652 100644 --- a/src/output.rs +++ b/src/output.rs @@ -13,7 +13,7 @@ use crate::{ config::Config, ipdb, proxy::{Proxy, ProxyType}, - utils::{CompactStrJoin as _, is_docker}, + utils::is_docker, }; fn compare_timeout(a: &Proxy, b: &Proxy) -> Ordering { @@ -226,8 +226,15 @@ fn create_proxy_list_str<'a, I>( where I: IntoIterator, { - proxies - .into_iter() - .map(move |proxy| proxy.to_string(include_protocol)) - .join("\n") + let mut out = compact_str::CompactString::const_new(""); + let mut first = true; + for proxy in proxies { + if first { + first = false; + } else { + out.push('\n'); + } + proxy.write_string(&mut out, include_protocol); + } + out } diff --git a/src/proxy.rs b/src/proxy.rs index 381a017..82beabb 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -131,12 +131,11 @@ impl Proxy { Ok(()) } - pub fn to_string( + pub fn write_string( &self, + s: &mut compact_str::CompactString, include_protocol: bool, - ) -> compact_str::CompactString { - let mut s = compact_str::CompactString::const_new(""); - + ) { if include_protocol { s.push_str(self.protocol.as_str()); s.push_str("://"); @@ -154,7 +153,14 @@ impl Proxy { s.push_str(&self.host); s.push(':'); s.push_str(itoa::Buffer::new().format(self.port)); + } + pub fn to_string( + &self, + include_protocol: bool, + ) -> compact_str::CompactString { + let mut s = compact_str::CompactString::const_new(""); + self.write_string(&mut s, include_protocol); s } } diff --git a/src/raw_config.rs b/src/raw_config.rs index 16ceec3..ffe4bf3 100644 --- a/src/raw_config.rs +++ b/src/raw_config.rs @@ -7,7 +7,7 @@ use std::{ use color_eyre::eyre::WrapErr as _; use serde::Deserialize as _; -use crate::{HashMap, http::BasicAuth, utils::CompactStrJoin as _}; +use crate::{HashMap, http::BasicAuth}; fn validate_positive_f64<'de, D: serde::Deserializer<'de>>( deserializer: D, @@ -40,12 +40,24 @@ where let type_label = match allowed_schemes { [] => "".into(), [single] => compact_str::format_compact!("'{single}'"), - [rest @ .., last] => compact_str::format_compact!( - "{} or '{last}'", - rest.iter() - .map(|s| compact_str::format_compact!("'{s}'")) - .join(", ") - ), + [rest @ .., last] => { + let mut t = compact_str::CompactString::const_new(""); + let mut first = true; + for s in rest { + if first { + first = false; + } else { + t.push_str(", "); + } + t.push('\''); + t.push_str(s); + t.push('\''); + } + t.push_str(" or '"); + t.push_str(last); + t.push('\''); + t + } }; Err(serde::de::Error::custom(compact_str::format_compact!( "'{s}' is not a valid {type_label} url"