perf: optimize profile handle memory usage

This commit is contained in:
Tunglies
2025-11-04 10:04:36 +08:00
parent a5e6a35dea
commit bae584b1ab
3 changed files with 42 additions and 48 deletions

View File

@@ -284,10 +284,10 @@ async fn validate_new_profile(new_profile: &String) -> Result<(), ()> {
} }
/// 执行配置更新并处理结果 /// 执行配置更新并处理结果
async fn restore_previous_profile(prev_profile: String) -> CmdResult<()> { async fn restore_previous_profile(prev_profile: &String) -> CmdResult<()> {
logging!(info, Type::Cmd, "尝试恢复到之前的配置: {}", prev_profile); logging!(info, Type::Cmd, "尝试恢复到之前的配置: {}", prev_profile);
let restore_profiles = IProfiles { let restore_profiles = IProfiles {
current: Some(prev_profile), current: Some(prev_profile.to_owned()),
items: None, items: None,
}; };
Config::profiles() Config::profiles()
@@ -304,7 +304,7 @@ async fn restore_previous_profile(prev_profile: String) -> CmdResult<()> {
Ok(()) Ok(())
} }
async fn handle_success(current_value: Option<String>) -> CmdResult<bool> { async fn handle_success(current_value: Option<&String>) -> CmdResult<bool> {
Config::profiles().await.apply(); Config::profiles().await.apply();
handle::Handle::refresh_clash(); handle::Handle::refresh_clash();
@@ -320,9 +320,9 @@ async fn handle_success(current_value: Option<String>) -> CmdResult<bool> {
logging!(warn, Type::Cmd, "Warning: 异步保存配置文件失败: {e}"); logging!(warn, Type::Cmd, "Warning: 异步保存配置文件失败: {e}");
} }
if let Some(current) = &current_value { if let Some(current) = current_value {
logging!(info, Type::Cmd, "向前端发送配置变更事件: {}", current,); logging!(info, Type::Cmd, "向前端发送配置变更事件: {}", current);
handle::Handle::notify_profile_changed(current.clone()); handle::Handle::notify_profile_changed(current.to_owned());
} }
Ok(true) Ok(true)
@@ -330,7 +330,7 @@ async fn handle_success(current_value: Option<String>) -> CmdResult<bool> {
async fn handle_validation_failure( async fn handle_validation_failure(
error_msg: String, error_msg: String,
current_profile: Option<String>, current_profile: Option<&String>,
) -> CmdResult<bool> { ) -> CmdResult<bool> {
logging!(warn, Type::Cmd, "配置验证失败: {}", error_msg); logging!(warn, Type::Cmd, "配置验证失败: {}", error_msg);
Config::profiles().await.discard(); Config::profiles().await.discard();
@@ -348,7 +348,7 @@ async fn handle_update_error<E: std::fmt::Display>(e: E) -> CmdResult<bool> {
Ok(false) Ok(false)
} }
async fn handle_timeout(current_profile: Option<String>) -> CmdResult<bool> { async fn handle_timeout(current_profile: Option<&String>) -> CmdResult<bool> {
let timeout_msg = "配置更新超时(30秒),可能是配置验证或核心通信阻塞"; let timeout_msg = "配置更新超时(30秒),可能是配置验证或核心通信阻塞";
logging!(error, Type::Cmd, "{}", timeout_msg); logging!(error, Type::Cmd, "{}", timeout_msg);
Config::profiles().await.discard(); Config::profiles().await.discard();
@@ -360,8 +360,8 @@ async fn handle_timeout(current_profile: Option<String>) -> CmdResult<bool> {
} }
async fn perform_config_update( async fn perform_config_update(
current_value: Option<String>, current_value: Option<&String>,
current_profile: Option<String>, current_profile: Option<&String>,
) -> CmdResult<bool> { ) -> CmdResult<bool> {
let update_result = tokio::time::timeout( let update_result = tokio::time::timeout(
Duration::from_secs(30), Duration::from_secs(30),
@@ -391,7 +391,8 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
defer! { defer! {
CURRENT_SWITCHING_PROFILE.store(false, Ordering::Release); CURRENT_SWITCHING_PROFILE.store(false, Ordering::Release);
} }
let target_profile = profiles.current.clone();
let target_profile = profiles.current.as_ref();
logging!( logging!(
info, info,
@@ -401,24 +402,21 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult<bool> {
); );
// 保存当前配置,以便在验证失败时恢复 // 保存当前配置,以便在验证失败时恢复
let current_profile = Config::profiles().await.latest_arc().current.clone(); let previous_profile = Config::profiles().await.data_arc().current.clone();
logging!(info, Type::Cmd, "当前配置: {:?}", current_profile); logging!(info, Type::Cmd, "当前配置: {:?}", previous_profile);
// 如果要切换配置,先检查目标配置文件是否有语法错误 // 如果要切换配置,先检查目标配置文件是否有语法错误
if let Some(new_profile) = profiles.current.as_ref() if let Some(switch_to_profile) = target_profile
&& current_profile.as_ref() != Some(new_profile) && previous_profile.as_ref() != Some(switch_to_profile)
&& validate_new_profile(new_profile).await.is_err() && validate_new_profile(switch_to_profile).await.is_err()
{ {
return Ok(false); return Ok(false);
} }
let _ = Config::profiles() let _ = Config::profiles()
.await .await
.edit_draft(|d| d.patch_config(&profiles)); .edit_draft(|d| d.patch_config(&profiles));
let current_value = profiles.current.clone(); perform_config_update(target_profile, previous_profile.as_ref()).await
perform_config_update(current_value, current_profile).await
} }
/// 根据profile name修改profiles /// 根据profile name修改profiles

View File

@@ -50,28 +50,26 @@ impl IProfiles {
} }
None None
} }
pub async fn new() -> Self { pub async fn new() -> Self {
match dirs::profiles_path() { let path = match dirs::profiles_path() {
Ok(path) => match help::read_yaml::<Self>(&path).await { Ok(p) => p,
Ok(mut profiles) => { Err(err) => {
if profiles.items.is_none() { logging!(error, Type::Config, "{err}");
profiles.items = Some(vec![]); return Self::default();
}
};
match help::read_yaml::<Self>(&path).await {
Ok(mut profiles) => {
let items = profiles.items.get_or_insert_with(Vec::new);
for item in items.iter_mut() {
if item.uid.is_none() {
item.uid = Some(help::get_uid("d").into());
} }
// compatible with the old old old version
if let Some(items) = profiles.items.as_mut() {
for item in items.iter_mut() {
if item.uid.is_none() {
item.uid = Some(help::get_uid("d").into());
}
}
}
profiles
} }
Err(err) => { profiles
logging!(error, Type::Config, "{err}"); }
Self::default()
}
},
Err(err) => { Err(err) => {
logging!(error, Type::Config, "{err}"); logging!(error, Type::Config, "{err}");
Self::default() Self::default()
@@ -433,12 +431,12 @@ impl IProfiles {
} }
/// 获取所有的profiles(uid名称) /// 获取所有的profiles(uid名称)
pub fn all_profile_uid_and_name(&self) -> Option<Vec<(String, String)>> { pub fn all_profile_uid_and_name(&self) -> Option<Vec<(&String, &String)>> {
self.items.as_ref().map(|items| { self.items.as_ref().map(|items| {
items items
.iter() .iter()
.filter_map(|e| { .filter_map(|e| {
if let (Some(uid), Some(name)) = (e.uid.clone(), e.name.clone()) { if let (Some(uid), Some(name)) = (e.uid.as_ref(), e.name.as_ref()) {
Some((uid, name)) Some((uid, name))
} else { } else {
None None

View File

@@ -318,11 +318,9 @@ impl Tray {
.unwrap_or("rule") .unwrap_or("rule")
.to_owned() .to_owned()
}; };
let profile_uid_and_name = Config::profiles() let profiles_config = Config::profiles().await;
.await let profiles_arc = profiles_config.latest_arc();
.latest_arc() let profile_uid_and_name = profiles_arc.all_profile_uid_and_name().unwrap_or_default();
.all_profile_uid_and_name()
.unwrap_or_default();
let is_lightweight_mode = is_in_lightweight_mode(); let is_lightweight_mode = is_in_lightweight_mode();
match app_handle.tray_by_id("main") { match app_handle.tray_by_id("main") {
@@ -666,7 +664,7 @@ fn create_hotkeys(hotkeys: &Option<Vec<String>>) -> HashMap<String, String> {
async fn create_profile_menu_item( async fn create_profile_menu_item(
app_handle: &AppHandle, app_handle: &AppHandle,
profile_uid_and_name: Vec<(String, String)>, profile_uid_and_name: Vec<(&String, &String)>,
) -> Result<Vec<CheckMenuItem<Wry>>> { ) -> Result<Vec<CheckMenuItem<Wry>>> {
let futures = profile_uid_and_name let futures = profile_uid_and_name
.iter() .iter()
@@ -870,7 +868,7 @@ async fn create_tray_menu(
system_proxy_enabled: bool, system_proxy_enabled: bool,
tun_mode_enabled: bool, tun_mode_enabled: bool,
tun_mode_available: bool, tun_mode_available: bool,
profile_uid_and_name: Vec<(String, String)>, profile_uid_and_name: Vec<(&String, &String)>,
is_lightweight_mode: bool, is_lightweight_mode: bool,
) -> Result<tauri::menu::Menu<Wry>> { ) -> Result<tauri::menu::Menu<Wry>> {
let current_proxy_mode = mode.unwrap_or(""); let current_proxy_mode = mode.unwrap_or("");