perf: update current_* methods to return references instead of owned Strings and decrease unnecessary arc clone

This commit is contained in:
Tunglies
2025-11-21 12:17:35 +08:00
parent 6a62009485
commit ee9e9182dc
2 changed files with 101 additions and 119 deletions

View File

@@ -555,28 +555,28 @@ impl PrfItem {
impl PrfItem { impl PrfItem {
/// 获取current指向的订阅的merge /// 获取current指向的订阅的merge
pub fn current_merge(&self) -> Option<String> { pub fn current_merge(&self) -> Option<&String> {
self.option.as_ref().and_then(|o| o.merge.clone()) self.option.as_ref().and_then(|o| o.merge.as_ref())
} }
/// 获取current指向的订阅的script /// 获取current指向的订阅的script
pub fn current_script(&self) -> Option<String> { pub fn current_script(&self) -> Option<&String> {
self.option.as_ref().and_then(|o| o.script.clone()) self.option.as_ref().and_then(|o| o.script.as_ref())
} }
/// 获取current指向的订阅的rules /// 获取current指向的订阅的rules
pub fn current_rules(&self) -> Option<String> { pub fn current_rules(&self) -> Option<&String> {
self.option.as_ref().and_then(|o| o.rules.clone()) self.option.as_ref().and_then(|o| o.rules.as_ref())
} }
/// 获取current指向的订阅的proxies /// 获取current指向的订阅的proxies
pub fn current_proxies(&self) -> Option<String> { pub fn current_proxies(&self) -> Option<&String> {
self.option.as_ref().and_then(|o| o.proxies.clone()) self.option.as_ref().and_then(|o| o.proxies.as_ref())
} }
/// 获取current指向的订阅的groups /// 获取current指向的订阅的groups
pub fn current_groups(&self) -> Option<String> { pub fn current_groups(&self) -> Option<&String> {
self.option.as_ref().and_then(|o| o.groups.clone()) self.option.as_ref().and_then(|o| o.groups.as_ref())
} }
} }

View File

@@ -13,12 +13,13 @@ use self::{
seq::{SeqMap, use_seq}, seq::{SeqMap, use_seq},
tun::use_tun, tun::use_tun,
}; };
use crate::constants;
use crate::utils::dirs; use crate::utils::dirs;
use crate::{config::Config, utils::tmpl}; use crate::{config::Config, utils::tmpl};
use crate::{config::IVerge, constants};
use clash_verge_logging::{Type, logging}; use clash_verge_logging::{Type, logging};
use serde_yaml_ng::{Mapping, Value}; use serde_yaml_ng::{Mapping, Value};
use smartstring::alias::String; use smartstring::alias::String;
use std::borrow::Cow;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use tokio::fs; use tokio::fs;
@@ -89,34 +90,41 @@ impl Default for ProfileItems {
} }
async fn get_config_values() -> ConfigValues { async fn get_config_values() -> ConfigValues {
let clash_config = { Config::clash().await.latest_arc().0.clone() }; let clash = Config::clash().await;
let clash_arc = clash.latest_arc();
let clash_config = clash_arc.0.clone();
drop(clash_arc);
drop(clash);
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled, enable_dns_settings) = { let verge = Config::verge().await;
let verge = Config::verge().await;
let verge = verge.latest_arc(); let verge_arc = verge.latest_arc();
( let IVerge {
Some(verge.get_valid_clash_core()), ref enable_tun_mode,
verge.enable_tun_mode.unwrap_or(false), ref enable_builtin_enhanced,
verge.enable_builtin_enhanced.unwrap_or(true), ref verge_socks_enabled,
verge.verge_socks_enabled.unwrap_or(false), ref verge_http_enabled,
verge.verge_http_enabled.unwrap_or(false), ref enable_dns_settings,
verge.enable_dns_settings.unwrap_or(false), ..
) } = **verge_arc;
};
let (clash_core, enable_tun, enable_builtin, socks_enabled, http_enabled, enable_dns_settings) = (
Some(verge_arc.get_valid_clash_core()),
enable_tun_mode.unwrap_or(false),
enable_builtin_enhanced.unwrap_or(true),
verge_socks_enabled.unwrap_or(false),
verge_http_enabled.unwrap_or(false),
enable_dns_settings.unwrap_or(false),
);
#[cfg(not(target_os = "windows"))] #[cfg(not(target_os = "windows"))]
let redir_enabled = { let redir_enabled = verge_arc.verge_redir_enabled.unwrap_or(false);
let verge = Config::verge().await;
let verge = verge.latest_arc();
verge.verge_redir_enabled.unwrap_or(false)
};
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
let tproxy_enabled = { let tproxy_enabled = verge_arc.verge_tproxy_enabled.unwrap_or(false);
let verge = Config::verge().await;
let verge = verge.latest_arc(); drop(verge_arc);
verge.verge_tproxy_enabled.unwrap_or(false) drop(verge);
};
ConfigValues { ConfigValues {
clash_config, clash_config,
@@ -135,66 +143,62 @@ async fn get_config_values() -> ConfigValues {
#[allow(clippy::cognitive_complexity)] #[allow(clippy::cognitive_complexity)]
async fn collect_profile_items() -> ProfileItems { async fn collect_profile_items() -> ProfileItems {
// 从profiles里拿东西 - 先收集需要的数据,然后释放锁 let profiles = Config::profiles().await;
let (current, merge_uid, script_uid, rules_uid, proxies_uid, groups_uid, name) = { let profiles_arc = profiles.latest_arc();
let current = { drop(profiles);
let profiles = Config::profiles().await;
let profiles_clone = profiles.latest_arc();
profiles_clone.current_mapping().await.unwrap_or_default()
};
let profiles = Config::profiles().await; let current = profiles_arc.current_mapping().await.unwrap_or_default();
let profiles_ref = profiles.latest_arc();
let current_profile_uid = match profiles_ref.get_current() {
Some(uid) => uid.clone(),
None => return ProfileItems::default(),
};
let current_item = match profiles_ref.get_item_arc(&current_profile_uid) { let current_profile_uid = match profiles_arc.get_current() {
Some(item) => item, Some(uid) => uid,
None => return ProfileItems::default(), None => {
}; drop(profiles_arc);
return ProfileItems::default();
let merge_uid = current_item }
.current_merge()
.unwrap_or_else(|| "Merge".into());
let script_uid = current_item
.current_script()
.unwrap_or_else(|| "Script".into());
let rules_uid = current_item
.current_rules()
.unwrap_or_else(|| "Rules".into());
let proxies_uid = current_item
.current_proxies()
.unwrap_or_else(|| "Proxies".into());
let groups_uid = current_item
.current_groups()
.unwrap_or_else(|| "Groups".into());
let name = profiles_ref
.get_item(&current_profile_uid)
.ok()
.and_then(|item| item.name.clone())
.unwrap_or_default();
(
current,
merge_uid,
script_uid,
rules_uid,
proxies_uid,
groups_uid,
name,
)
}; };
// 现在获取具体的items此时profiles锁已经释放 let current_item = match profiles_arc.get_item(current_profile_uid) {
Ok(item) => item,
Err(_) => {
drop(profiles_arc);
return ProfileItems::default();
}
};
let merge_uid: Cow<'_, str> = if let Some(s) = current_item.current_merge() {
Cow::Borrowed(s)
} else {
Cow::Owned("Merge".into())
};
let script_uid: Cow<'_, str> = if let Some(s) = current_item.current_script() {
Cow::Borrowed(s)
} else {
Cow::Owned("Script".into())
};
let rules_uid: Cow<'_, str> = if let Some(s) = current_item.current_rules() {
Cow::Borrowed(s)
} else {
Cow::Owned("Rules".into())
};
let proxies_uid: Cow<'_, str> = if let Some(s) = current_item.current_proxies() {
Cow::Borrowed(s)
} else {
Cow::Owned("Proxies".into())
};
let groups_uid: Cow<'_, str> = if let Some(s) = current_item.current_groups() {
Cow::Borrowed(s)
} else {
Cow::Owned("Groups".into())
};
let name = profiles_arc
.get_item(current_profile_uid)
.ok()
.and_then(|item| item.name.clone())
.unwrap_or_default();
let merge_item = { let merge_item = {
let item = { let item = profiles_arc.get_item(&merge_uid).ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item(&merge_uid).ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -207,11 +211,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let script_item = { let script_item = {
let item = { let item = profiles_arc.get_item(&script_uid).ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item(&script_uid).ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -224,11 +224,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let rules_item = { let rules_item = {
let item = { let item = profiles_arc.get_item(&rules_uid).ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item(&rules_uid).ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -241,11 +237,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let proxies_item = { let proxies_item = {
let item = { let item = profiles_arc.get_item(&proxies_uid).ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item(&proxies_uid).ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -258,11 +250,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let groups_item = { let groups_item = {
let item = { let item = profiles_arc.get_item(&groups_uid).ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item(&groups_uid).ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -275,11 +263,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let global_merge = { let global_merge = {
let item = { let item = profiles_arc.get_item("Merge").ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item("Merge").ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -292,11 +276,7 @@ async fn collect_profile_items() -> ProfileItems {
}); });
let global_script = { let global_script = {
let item = { let item = profiles_arc.get_item("Script").ok().cloned();
let profiles = Config::profiles().await;
let profiles = profiles.latest_arc();
profiles.get_item("Script").ok().cloned()
};
if let Some(item) = item { if let Some(item) = item {
<Option<ChainItem>>::from_async(&item).await <Option<ChainItem>>::from_async(&item).await
} else { } else {
@@ -308,6 +288,8 @@ async fn collect_profile_items() -> ProfileItems {
data: ChainType::Script(tmpl::ITEM_SCRIPT.into()), data: ChainType::Script(tmpl::ITEM_SCRIPT.into()),
}); });
drop(profiles_arc);
ProfileItems { ProfileItems {
config: current, config: current,
merge_item, merge_item,