diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index e09bcc9f7..6bd985be9 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1470,6 +1470,7 @@ dependencies = [ "serde", "serde_json", "tinytemplate", + "tokio", "walkdir", ] diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 5f1691cd0..4b0534d57 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -128,6 +128,11 @@ tauri-dev = [] tokio-trace = ["console-subscriber"] clippy = ["tauri/test"] +[[bench]] +name = "draft_benchmark" +path = "benches/draft_benchmark.rs" +harness = false + [profile.release] panic = "abort" codegen-units = 16 @@ -162,7 +167,7 @@ name = "app_lib" crate-type = ["staticlib", "cdylib", "rlib"] [dev-dependencies] -criterion = "0.7.0" +criterion = { version = "0.7.0", features = ["async_tokio"] } [lints.clippy] # Core categories - most important for code safety and correctness diff --git a/src-tauri/benches/draft_benchmark.rs b/src-tauri/benches/draft_benchmark.rs index 8f1515ed9..aac06a06a 100644 --- a/src-tauri/benches/draft_benchmark.rs +++ b/src-tauri/benches/draft_benchmark.rs @@ -1,91 +1,138 @@ use criterion::{Criterion, criterion_group, criterion_main}; use std::hint::black_box; +use tokio::runtime::Runtime; -// 业务模型 & Draft -use app_lib::config::Draft as DraftNew; +// 引入业务模型 & Draft 实现 use app_lib::config::IVerge; +use app_lib::utils::Draft as DraftNew; -// fn bench_apply_old(c: &mut Criterion) { -// c.bench_function("apply_draft_old", |b| { -// b.iter(|| { -// let verge = Box::new(IVerge { -// enable_auto_launch: Some(true), -// enable_tun_mode: Some(false), -// ..Default::default() -// }); +/// 创建测试数据 +fn make_draft() -> DraftNew> { + let verge = Box::new(IVerge { + enable_auto_launch: Some(true), + enable_tun_mode: Some(false), + ..Default::default() + }); + DraftNew::from(verge) +} -// let draft = DraftOld::from(black_box(verge)); - -// { -// let mut d = draft.draft_mut(); -// d.enable_auto_launch = Some(false); -// } - -// let _ = draft.apply(); -// }); -// }); -// } - -// fn bench_discard_old(c: &mut Criterion) { -// c.bench_function("discard_draft_old", |b| { -// b.iter(|| { -// let verge = Box::new(IVerge::default()); -// let draft = DraftOld::from(black_box(verge)); - -// { -// let mut d = draft.draft_mut(); -// d.enable_auto_launch = Some(false); -// } - -// let _ = draft.discard(); -// }); -// }); -// } - -/// 基准:修改草稿并 apply() -fn bench_apply_new(c: &mut Criterion) { - c.bench_function("apply_draft_new", |b| { +/// 基准:只读 data_ref(正式数据) +fn bench_data_ref(c: &mut Criterion) { + c.bench_function("draft_data_ref", |b| { b.iter(|| { - let verge = Box::new(IVerge { - enable_auto_launch: Some(true), - enable_tun_mode: Some(false), - ..Default::default() - }); + let draft = make_draft(); + let data = draft.data_ref(); + black_box(data.enable_auto_launch); + }); + }); +} - let draft = DraftNew::from(black_box(verge)); +/// 基准:可写 data_mut(正式数据) +fn bench_data_mut(c: &mut Criterion) { + c.bench_function("draft_data_mut", |b| { + b.iter(|| { + let draft = make_draft(); + let mut data = draft.data_mut(); + data.enable_tun_mode = Some(true); + black_box(data.enable_tun_mode); + }); + }); +} +/// 基准:首次创建草稿(会触发 clone) +fn bench_draft_mut_first(c: &mut Criterion) { + c.bench_function("draft_draft_mut_first", |b| { + b.iter(|| { + let draft = make_draft(); + let mut d = draft.draft_mut(); + d.enable_auto_launch = Some(false); + black_box(d.enable_auto_launch); + }); + }); +} + +/// 基准:重复 draft_mut(已存在草稿,不再 clone) +fn bench_draft_mut_existing(c: &mut Criterion) { + c.bench_function("draft_draft_mut_existing", |b| { + b.iter(|| { + let draft = make_draft(); + { + let mut first = draft.draft_mut(); + first.enable_tun_mode = Some(true); + } + let mut second = draft.draft_mut(); + second.enable_tun_mode = Some(false); + black_box(second.enable_tun_mode); + }); + }); +} + +/// 基准:零拷贝读取最新视图(latest_ref) +fn bench_latest_ref(c: &mut Criterion) { + c.bench_function("draft_latest_ref", |b| { + b.iter(|| { + let draft = make_draft(); + let latest = draft.latest_ref(); + black_box(latest.enable_auto_launch); + }); + }); +} + +/// 基准:apply(提交草稿) +fn bench_apply(c: &mut Criterion) { + c.bench_function("draft_apply", |b| { + b.iter(|| { + let draft = make_draft(); { let mut d = draft.draft_mut(); d.enable_auto_launch = Some(false); } - let _ = draft.apply(); }); }); } -/// 基准:修改草稿并 discard() -fn bench_discard_new(c: &mut Criterion) { - c.bench_function("discard_draft_new", |b| { +/// 基准:discard(丢弃草稿) +fn bench_discard(c: &mut Criterion) { + c.bench_function("draft_discard", |b| { b.iter(|| { - let verge = Box::new(IVerge::default()); - let draft = DraftNew::from(black_box(verge)); - + let draft = make_draft(); { let mut d = draft.draft_mut(); d.enable_auto_launch = Some(false); } - let _ = draft.discard(); }); }); } +/// 基准:异步 with_data_modify +fn bench_with_data_modify(c: &mut Criterion) { + let rt = Runtime::new().unwrap(); + + c.bench_function("draft_with_data_modify", |b| { + b.to_async(&rt).iter(|| async { + let draft = make_draft(); + let _res: Result<(), anyhow::Error> = draft + .with_data_modify(|mut box_data| async move { + box_data.enable_auto_launch = + Some(!box_data.enable_auto_launch.unwrap_or(false)); + Ok((box_data, ())) + }) + .await; + }); + }); +} + criterion_group!( benches, - // bench_apply_old, - // bench_discard_old, - bench_apply_new, - bench_discard_new + bench_data_ref, + bench_data_mut, + bench_draft_mut_first, + bench_draft_mut_existing, + bench_latest_ref, + bench_apply, + bench_discard, + bench_with_data_modify ); criterion_main!(benches); diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index e3219cc60..c6be0bae0 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -1,9 +1,9 @@ -use super::{Draft, IClashTemp, IProfiles, IRuntime, IVerge}; +use super::{IClashTemp, IProfiles, IRuntime, IVerge}; use crate::{ config::{PrfItem, profiles_append_item_safe}, core::{CoreManager, handle}, enhance, logging, - utils::{dirs, help, logging::Type}, + utils::{Draft, dirs, help, logging::Type}, }; use anyhow::{Result, anyhow}; use backoff::{Error as BackoffError, ExponentialBackoff}; diff --git a/src-tauri/src/config/mod.rs b/src-tauri/src/config/mod.rs index 511687571..342c11f47 100644 --- a/src-tauri/src/config/mod.rs +++ b/src-tauri/src/config/mod.rs @@ -1,16 +1,13 @@ mod clash; #[allow(clippy::module_inception)] mod config; -mod draft; mod encrypt; mod prfitem; pub mod profiles; mod runtime; mod verge; -pub use self::{ - clash::*, config::*, draft::*, encrypt::*, prfitem::*, profiles::*, runtime::*, verge::*, -}; +pub use self::{clash::*, config::*, encrypt::*, prfitem::*, profiles::*, runtime::*, verge::*}; pub const DEFAULT_PAC: &str = r#"function FindProxyForURL(url, host) { return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;"; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 00a815a62..9f501c741 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -8,7 +8,7 @@ mod enhance; mod feat; mod module; mod process; -mod utils; +pub mod utils; #[cfg(target_os = "macos")] use crate::utils::window_manager::WindowManager; use crate::{ diff --git a/src-tauri/src/config/draft.rs b/src-tauri/src/utils/draft.rs similarity index 99% rename from src-tauri/src/config/draft.rs rename to src-tauri/src/utils/draft.rs index 3da3029c2..044f6f1fa 100644 --- a/src-tauri/src/config/draft.rs +++ b/src-tauri/src/utils/draft.rs @@ -109,7 +109,7 @@ impl Draft> { #[test] fn test_draft_box() { - use super::IVerge; + use crate::config::IVerge; // 1. 创建 Draft> let verge = Box::new(IVerge { diff --git a/src-tauri/src/utils/mod.rs b/src-tauri/src/utils/mod.rs index 74b895bdb..787351a0a 100644 --- a/src-tauri/src/utils/mod.rs +++ b/src-tauri/src/utils/mod.rs @@ -1,5 +1,6 @@ pub mod autostart; pub mod dirs; +pub mod draft; pub mod format; pub mod help; pub mod i18n; @@ -12,3 +13,5 @@ pub mod server; pub mod singleton; pub mod tmpl; pub mod window_manager; + +pub use draft::Draft; diff --git a/src-tauri/src/utils/network.rs b/src-tauri/src/utils/network.rs index 1df28399a..55fa65ce8 100644 --- a/src-tauri/src/utils/network.rs +++ b/src-tauri/src/utils/network.rs @@ -61,6 +61,12 @@ pub struct NetworkManager { connection_error_count: Mutex, } +impl Default for NetworkManager { + fn default() -> Self { + Self::new() + } +} + impl NetworkManager { pub fn new() -> Self { Self {