mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-29 00:35:38 +08:00
feat: implement draft management system for concurrent editing and committing of data
This commit is contained in:
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@@ -1470,6 +1470,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tinytemplate",
|
"tinytemplate",
|
||||||
|
"tokio",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,11 @@ tauri-dev = []
|
|||||||
tokio-trace = ["console-subscriber"]
|
tokio-trace = ["console-subscriber"]
|
||||||
clippy = ["tauri/test"]
|
clippy = ["tauri/test"]
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "draft_benchmark"
|
||||||
|
path = "benches/draft_benchmark.rs"
|
||||||
|
harness = false
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
codegen-units = 16
|
codegen-units = 16
|
||||||
@@ -162,7 +167,7 @@ name = "app_lib"
|
|||||||
crate-type = ["staticlib", "cdylib", "rlib"]
|
crate-type = ["staticlib", "cdylib", "rlib"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = "0.7.0"
|
criterion = { version = "0.7.0", features = ["async_tokio"] }
|
||||||
|
|
||||||
[lints.clippy]
|
[lints.clippy]
|
||||||
# Core categories - most important for code safety and correctness
|
# Core categories - most important for code safety and correctness
|
||||||
|
|||||||
@@ -1,91 +1,138 @@
|
|||||||
use criterion::{Criterion, criterion_group, criterion_main};
|
use criterion::{Criterion, criterion_group, criterion_main};
|
||||||
use std::hint::black_box;
|
use std::hint::black_box;
|
||||||
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
// 业务模型 & Draft
|
// 引入业务模型 & Draft 实现
|
||||||
use app_lib::config::Draft as DraftNew;
|
|
||||||
use app_lib::config::IVerge;
|
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| {
|
fn make_draft() -> DraftNew<Box<IVerge>> {
|
||||||
// b.iter(|| {
|
|
||||||
// let verge = Box::new(IVerge {
|
|
||||||
// enable_auto_launch: Some(true),
|
|
||||||
// enable_tun_mode: Some(false),
|
|
||||||
// ..Default::default()
|
|
||||||
// });
|
|
||||||
|
|
||||||
// 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| {
|
|
||||||
b.iter(|| {
|
|
||||||
let verge = Box::new(IVerge {
|
let verge = Box::new(IVerge {
|
||||||
enable_auto_launch: Some(true),
|
enable_auto_launch: Some(true),
|
||||||
enable_tun_mode: Some(false),
|
enable_tun_mode: Some(false),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
DraftNew::from(verge)
|
||||||
|
}
|
||||||
|
|
||||||
let draft = DraftNew::from(black_box(verge));
|
/// 基准:只读 data_ref(正式数据)
|
||||||
|
fn bench_data_ref(c: &mut Criterion) {
|
||||||
|
c.bench_function("draft_data_ref", |b| {
|
||||||
|
b.iter(|| {
|
||||||
|
let draft = make_draft();
|
||||||
|
let data = draft.data_ref();
|
||||||
|
black_box(data.enable_auto_launch);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 基准:可写 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();
|
let mut d = draft.draft_mut();
|
||||||
d.enable_auto_launch = Some(false);
|
d.enable_auto_launch = Some(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = draft.apply();
|
let _ = draft.apply();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 基准:修改草稿并 discard()
|
/// 基准:discard(丢弃草稿)
|
||||||
fn bench_discard_new(c: &mut Criterion) {
|
fn bench_discard(c: &mut Criterion) {
|
||||||
c.bench_function("discard_draft_new", |b| {
|
c.bench_function("draft_discard", |b| {
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let verge = Box::new(IVerge::default());
|
let draft = make_draft();
|
||||||
let draft = DraftNew::from(black_box(verge));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut d = draft.draft_mut();
|
let mut d = draft.draft_mut();
|
||||||
d.enable_auto_launch = Some(false);
|
d.enable_auto_launch = Some(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = draft.discard();
|
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!(
|
criterion_group!(
|
||||||
benches,
|
benches,
|
||||||
// bench_apply_old,
|
bench_data_ref,
|
||||||
// bench_discard_old,
|
bench_data_mut,
|
||||||
bench_apply_new,
|
bench_draft_mut_first,
|
||||||
bench_discard_new
|
bench_draft_mut_existing,
|
||||||
|
bench_latest_ref,
|
||||||
|
bench_apply,
|
||||||
|
bench_discard,
|
||||||
|
bench_with_data_modify
|
||||||
);
|
);
|
||||||
criterion_main!(benches);
|
criterion_main!(benches);
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use super::{Draft, IClashTemp, IProfiles, IRuntime, IVerge};
|
use super::{IClashTemp, IProfiles, IRuntime, IVerge};
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{PrfItem, profiles_append_item_safe},
|
config::{PrfItem, profiles_append_item_safe},
|
||||||
core::{CoreManager, handle},
|
core::{CoreManager, handle},
|
||||||
enhance, logging,
|
enhance, logging,
|
||||||
utils::{dirs, help, logging::Type},
|
utils::{Draft, dirs, help, logging::Type},
|
||||||
};
|
};
|
||||||
use anyhow::{Result, anyhow};
|
use anyhow::{Result, anyhow};
|
||||||
use backoff::{Error as BackoffError, ExponentialBackoff};
|
use backoff::{Error as BackoffError, ExponentialBackoff};
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
mod clash;
|
mod clash;
|
||||||
#[allow(clippy::module_inception)]
|
#[allow(clippy::module_inception)]
|
||||||
mod config;
|
mod config;
|
||||||
mod draft;
|
|
||||||
mod encrypt;
|
mod encrypt;
|
||||||
mod prfitem;
|
mod prfitem;
|
||||||
pub mod profiles;
|
pub mod profiles;
|
||||||
mod runtime;
|
mod runtime;
|
||||||
mod verge;
|
mod verge;
|
||||||
|
|
||||||
pub use self::{
|
pub use self::{clash::*, config::*, encrypt::*, prfitem::*, profiles::*, runtime::*, verge::*};
|
||||||
clash::*, config::*, draft::*, encrypt::*, prfitem::*, profiles::*, runtime::*, verge::*,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const DEFAULT_PAC: &str = r#"function FindProxyForURL(url, host) {
|
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;";
|
return "PROXY 127.0.0.1:%mixed-port%; SOCKS5 127.0.0.1:%mixed-port%; DIRECT;";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ mod enhance;
|
|||||||
mod feat;
|
mod feat;
|
||||||
mod module;
|
mod module;
|
||||||
mod process;
|
mod process;
|
||||||
mod utils;
|
pub mod utils;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use crate::utils::window_manager::WindowManager;
|
use crate::utils::window_manager::WindowManager;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ impl<T: Clone + ToOwned> Draft<Box<T>> {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_draft_box() {
|
fn test_draft_box() {
|
||||||
use super::IVerge;
|
use crate::config::IVerge;
|
||||||
|
|
||||||
// 1. 创建 Draft<Box<IVerge>>
|
// 1. 创建 Draft<Box<IVerge>>
|
||||||
let verge = Box::new(IVerge {
|
let verge = Box::new(IVerge {
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
pub mod autostart;
|
pub mod autostart;
|
||||||
pub mod dirs;
|
pub mod dirs;
|
||||||
|
pub mod draft;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
pub mod help;
|
pub mod help;
|
||||||
pub mod i18n;
|
pub mod i18n;
|
||||||
@@ -12,3 +13,5 @@ pub mod server;
|
|||||||
pub mod singleton;
|
pub mod singleton;
|
||||||
pub mod tmpl;
|
pub mod tmpl;
|
||||||
pub mod window_manager;
|
pub mod window_manager;
|
||||||
|
|
||||||
|
pub use draft::Draft;
|
||||||
|
|||||||
@@ -61,6 +61,12 @@ pub struct NetworkManager {
|
|||||||
connection_error_count: Mutex<usize>,
|
connection_error_count: Mutex<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for NetworkManager {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl NetworkManager {
|
impl NetworkManager {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user