mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-01-28 07:14:40 +08:00
perf: refactor IRuntime to use HashSet for exists_keys and improve related functions performance
This commit is contained in:
@@ -1,79 +1,90 @@
|
||||
use serde_yaml_ng::{Mapping, Value};
|
||||
use smartstring::alias::String;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
const PATCH_CONFIG_INNER: [&str; 4] = ["allow-lan", "ipv6", "log-level", "unified-delay"];
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
pub struct IRuntime {
|
||||
pub config: Option<Mapping>,
|
||||
// 记录在订阅中(包括merge和script生成的)出现过的keys
|
||||
// 这些keys不一定都生效
|
||||
// TODO 或许我们可以用 hashset 来存储以提升查询效率
|
||||
pub exists_keys: Vec<String>,
|
||||
pub exists_keys: HashSet<String>,
|
||||
// TODO 或许可以用 FixMap 来存储以提升效率
|
||||
pub chain_logs: HashMap<String, Vec<(String, String)>>,
|
||||
}
|
||||
|
||||
impl IRuntime {
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
// 这里只更改 allow-lan | ipv6 | log-level | tun
|
||||
#[inline]
|
||||
pub fn patch_config(&mut self, patch: Mapping) {
|
||||
if let Some(config) = self.config.as_mut() {
|
||||
["allow-lan", "ipv6", "log-level", "unified-delay"]
|
||||
.into_iter()
|
||||
.for_each(|key| {
|
||||
if let Some(value) = patch.get(key).to_owned() {
|
||||
config.insert(key.into(), value.clone());
|
||||
}
|
||||
});
|
||||
let config = if let Some(config) = self.config.as_mut() {
|
||||
config
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
let patch_tun = patch.get("tun");
|
||||
if patch_tun.is_some() {
|
||||
let tun = config.get("tun");
|
||||
let mut tun: Mapping = tun.map_or_else(Mapping::new, |val| {
|
||||
val.as_mapping().cloned().unwrap_or_else(Mapping::new)
|
||||
});
|
||||
let patch_tun = patch_tun.map_or_else(Mapping::new, |val| {
|
||||
val.as_mapping().cloned().unwrap_or_else(Mapping::new)
|
||||
});
|
||||
use_keys(&patch_tun).into_iter().for_each(|key| {
|
||||
if let Some(value) = patch_tun.get(key.as_str()) {
|
||||
for key in PATCH_CONFIG_INNER.iter() {
|
||||
if let Some(value) = patch.get(key) {
|
||||
config.insert((*key).into(), value.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let patch_tun = patch.get("tun");
|
||||
if let Some(patch_tun_value) = patch_tun {
|
||||
let mut tun = config
|
||||
.get("tun")
|
||||
.and_then(|val| val.as_mapping())
|
||||
.cloned()
|
||||
.unwrap_or_else(Mapping::new);
|
||||
|
||||
if let Some(patch_tun_mapping) = patch_tun_value.as_mapping() {
|
||||
for key in use_keys(patch_tun_mapping) {
|
||||
if let Some(value) = patch_tun_mapping.get(key.as_str()) {
|
||||
tun.insert(Value::from(key.as_str()), value.clone());
|
||||
}
|
||||
});
|
||||
|
||||
config.insert("tun".into(), Value::from(tun));
|
||||
}
|
||||
}
|
||||
|
||||
config.insert("tun".into(), Value::from(tun));
|
||||
}
|
||||
}
|
||||
|
||||
// 传入none 为删除
|
||||
#[inline]
|
||||
pub fn update_proxy_chain_config(&mut self, proxy_chain_config: Option<Value>) {
|
||||
if let Some(config) = self.config.as_mut() {
|
||||
if let Some(Value::Sequence(proxies)) = config.get_mut("proxies") {
|
||||
proxies.iter_mut().for_each(|proxy| {
|
||||
if let Some(proxy) = proxy.as_mapping_mut()
|
||||
&& proxy.get("dialer-proxy").is_some()
|
||||
{
|
||||
proxy.remove("dialer-proxy");
|
||||
}
|
||||
});
|
||||
}
|
||||
let config = if let Some(config) = self.config.as_mut() {
|
||||
config
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
if let Some(Value::Sequence(dialer_proxies)) = proxy_chain_config
|
||||
&& let Some(Value::Sequence(proxies)) = config.get_mut("proxies")
|
||||
{
|
||||
for (i, dialer_proxy) in dialer_proxies.iter().enumerate() {
|
||||
if let Some(Value::Mapping(proxy)) = proxies
|
||||
.iter_mut()
|
||||
.find(|proxy| proxy.get("name") == Some(dialer_proxy))
|
||||
&& i != 0
|
||||
&& let Some(dialer_proxy) = dialer_proxies.get(i - 1)
|
||||
{
|
||||
proxy.insert("dialer-proxy".into(), dialer_proxy.to_owned());
|
||||
}
|
||||
if let Some(Value::Sequence(proxies)) = config.get_mut("proxies") {
|
||||
proxies.iter_mut().for_each(|proxy| {
|
||||
if let Some(proxy) = proxy.as_mapping_mut()
|
||||
&& proxy.get("dialer-proxy").is_some()
|
||||
{
|
||||
proxy.remove("dialer-proxy");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if let Some(Value::Sequence(dialer_proxies)) = proxy_chain_config
|
||||
&& let Some(Value::Sequence(proxies)) = config.get_mut("proxies")
|
||||
{
|
||||
for (i, dialer_proxy) in dialer_proxies.iter().enumerate() {
|
||||
if let Some(Value::Mapping(proxy)) = proxies
|
||||
.iter_mut()
|
||||
.find(|proxy| proxy.get("name") == Some(dialer_proxy))
|
||||
&& i != 0
|
||||
&& let Some(dialer_proxy) = dialer_proxies.get(i - 1)
|
||||
{
|
||||
proxy.insert("dialer-proxy".into(), dialer_proxy.to_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,7 +92,8 @@ impl IRuntime {
|
||||
}
|
||||
|
||||
// TODO 完整迁移 enhance 行为后移除
|
||||
fn use_keys(config: &Mapping) -> Vec<String> {
|
||||
#[inline]
|
||||
fn use_keys<'a>(config: &'a Mapping) -> impl Iterator<Item = String> + 'a {
|
||||
config
|
||||
.iter()
|
||||
.filter_map(|(key, _)| key.as_str())
|
||||
@@ -90,5 +102,4 @@ fn use_keys(config: &Mapping) -> Vec<String> {
|
||||
s.make_ascii_lowercase();
|
||||
s
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use anyhow::{Context as _, anyhow};
|
||||
use clash_verge_logging::{Type, logging_error};
|
||||
use serde_yaml_ng::Mapping;
|
||||
use smartstring::alias::String;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
/// 获取运行时配置
|
||||
#[tauri::command]
|
||||
@@ -31,7 +31,7 @@ pub async fn get_runtime_yaml() -> CmdResult<String> {
|
||||
|
||||
/// 获取运行时存在的键
|
||||
#[tauri::command]
|
||||
pub async fn get_runtime_exists() -> CmdResult<Vec<String>> {
|
||||
pub async fn get_runtime_exists() -> CmdResult<HashSet<String>> {
|
||||
Ok(Config::runtime().await.latest_arc().exists_keys.clone())
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use anyhow::{Result, anyhow};
|
||||
use clash_verge_logging::{Type, logging};
|
||||
use clash_verge_types::runtime::IRuntime;
|
||||
use smartstring::alias::String;
|
||||
use std::{path::PathBuf, time::Instant};
|
||||
use std::{collections::HashSet, path::PathBuf, time::Instant};
|
||||
use tauri_plugin_mihomo::Error as MihomoError;
|
||||
|
||||
impl CoreManager {
|
||||
@@ -22,7 +22,7 @@ impl CoreManager {
|
||||
Config::runtime().await.edit_draft(|d| {
|
||||
*d = IRuntime {
|
||||
config: Some(clash_config.to_owned()),
|
||||
exists_keys: vec![],
|
||||
exists_keys: HashSet::new(),
|
||||
chain_logs: Default::default(),
|
||||
}
|
||||
});
|
||||
|
||||
@@ -597,7 +597,7 @@ async fn apply_dns_settings(mut config: Mapping, enable_dns_settings: bool) -> M
|
||||
|
||||
/// Enhance mode
|
||||
/// 返回最终订阅、该订阅包含的键、和script执行的结果
|
||||
pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
pub async fn enhance() -> (Mapping, HashSet<String>, HashMap<String, ResultLog>) {
|
||||
// gather config values
|
||||
let cfg_vals = get_config_values().await;
|
||||
let ConfigValues {
|
||||
@@ -667,11 +667,10 @@ pub async fn enhance() -> (Mapping, Vec<String>, HashMap<String, ResultLog>) {
|
||||
// dns settings
|
||||
config = apply_dns_settings(config, enable_dns_settings).await;
|
||||
|
||||
let mut exists_set = HashSet::new();
|
||||
exists_set.extend(exists_keys);
|
||||
let exists_keys: Vec<String> = exists_set.into_iter().collect();
|
||||
let mut exists_keys_set = HashSet::new();
|
||||
exists_keys_set.extend(exists_keys);
|
||||
|
||||
(config, exists_keys, result_map)
|
||||
(config, exists_keys_set, result_map)
|
||||
}
|
||||
|
||||
#[allow(clippy::expect_used)]
|
||||
|
||||
Reference in New Issue
Block a user