perf(draft): optimize memory layout by removing double indirection & implemented optimistic locking via Arc::ptr_eq for with_data_modify (#5942)

* perf(draft): optimize memory layout by removing double indirection

- Replace `Arc<Box<T>>` with `Arc<T>` to reduce pointer chasing and memory overhead.
- Leverage `Arc::from(Box<T>)` in async modify path for efficient ownership transfer.
- Fix race conditions in `edit_draft` by ensuring atomicity under write lock.
- Performance improved by ~16-24% across all operations (based on Criterion bench).

Benchmarks:
- latest_arc:     41.1ns (-24.2%)
- edit_draft:     92.2ns (-17.6%)
- apply:          89.8ns (-17.7%)
- async_modify:   66.0ns (-16.6%)

* perf(draft): implemented optimistic locking via Arc::ptr_eq for with_data_modify

Benchmarks confirm only a negligible ~2% (1.3ns) overhead for async operations, ensuring total data integrity during concurrent updates.
This commit is contained in:
Tunglies
2025-12-25 16:44:23 +08:00
committed by GitHub
parent 1c044f053f
commit f9b8a658a1
5 changed files with 26 additions and 36 deletions

View File

@@ -16,7 +16,7 @@ use crate::{
ret_err,
utils::{dirs, help},
};
use clash_verge_draft::SharedBox;
use clash_verge_draft::SharedDraft;
use clash_verge_logging::{Type, logging};
use scopeguard::defer;
use smartstring::alias::String;
@@ -26,7 +26,7 @@ use std::time::Duration;
static CURRENT_SWITCHING_PROFILE: AtomicBool = AtomicBool::new(false);
#[tauri::command]
pub async fn get_profiles() -> CmdResult<SharedBox<IProfiles>> {
pub async fn get_profiles() -> CmdResult<SharedDraft<IProfiles>> {
logging!(debug, Type::Cmd, "获取配置文件列表");
let draft = Config::profiles().await;
let data = draft.data_arc();

View File

@@ -1,10 +1,10 @@
use super::CmdResult;
use crate::{cmd::StringifyErr as _, config::IVerge, feat};
use clash_verge_draft::SharedBox;
use clash_verge_draft::SharedDraft;
/// 获取Verge配置
#[tauri::command]
pub async fn get_verge_config() -> CmdResult<SharedBox<IVerge>> {
pub async fn get_verge_config() -> CmdResult<SharedDraft<IVerge>> {
feat::fetch_verge_config().await.stringify_err()
}

View File

@@ -106,7 +106,7 @@ async fn get_config_values() -> ConfigValues {
ref verge_http_enabled,
ref enable_dns_settings,
..
} = **verge_arc;
} = *verge_arc;
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled, enable_dns_settings) = (
Some(verge_arc.get_valid_clash_core()),

View File

@@ -4,7 +4,7 @@ use crate::{
module::{auto_backup::AutoBackupManager, lightweight},
};
use anyhow::Result;
use clash_verge_draft::SharedBox;
use clash_verge_draft::SharedDraft;
use clash_verge_logging::{Type, logging, logging_error};
use serde_yaml_ng::Mapping;
@@ -269,7 +269,7 @@ pub async fn patch_verge(patch: &IVerge, not_save_file: bool) -> Result<()> {
Ok(())
}
pub async fn fetch_verge_config() -> Result<SharedBox<IVerge>> {
pub async fn fetch_verge_config() -> Result<SharedDraft<IVerge>> {
let draft = Config::verge().await;
let data = draft.data_arc();
Ok(data)