Merge pull request #406 from linanwanttodo/main

perf(desktop): on-demand webview lifecycle and mimalloc allocator
This commit is contained in:
leokun
2026-09-15 22:43:17 +08:00
committed by GitHub
5 changed files with 81 additions and 51 deletions
Generated
+19
View File
@@ -1177,6 +1177,7 @@ dependencies = [
"axum",
"cursor-server",
"libc",
"mimalloc",
"rfd",
"serde",
"serde_json",
@@ -3417,6 +3418,15 @@ version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
[[package]]
name = "libmimalloc-sys"
version = "0.1.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9"
dependencies = [
"cc",
]
[[package]]
name = "libredox"
version = "0.1.19"
@@ -3604,6 +3614,15 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mimalloc"
version = "0.1.52"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862"
dependencies = [
"libmimalloc-sys",
]
[[package]]
name = "mime"
version = "0.3.17"
+1
View File
@@ -15,6 +15,7 @@ tauri-build = { version = "2", features = [] }
axum = "0.8"
cursor-server = { path = "../../../server" }
libc = "0.2"
mimalloc = "0.1"
rfd = "0.15"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
+32 -21
View File
@@ -36,6 +36,7 @@ struct DesktopRuntime {
shutdown: CancellationToken,
server: Mutex<Option<JoinHandle<Result<()>>>>,
exiting: AtomicBool,
server_addr: std::net::SocketAddr,
}
#[tauri::command]
@@ -141,6 +142,21 @@ fn create_main_window(
builder.build()
}
/// 按需打开主窗口:webview 仅在需要界面时创建,关闭窗口即销毁释放内存。
pub(crate) fn open_main_window(app: &AppHandle) -> tauri::Result<()> {
if let Some(window) = app.get_webview_window(MAIN_WINDOW_LABEL) {
let _ = window.unminimize();
let _ = window.show();
let _ = window.set_focus();
return Ok(());
}
let address = app.state::<DesktopRuntime>().server_addr;
let window = create_main_window(app, address)?;
window.show()?;
window.set_focus()?;
Ok(())
}
pub fn run() -> ExitCode {
let diagnostics = match StartupDiagnostics::initialize() {
Ok(diagnostics) => diagnostics,
@@ -184,7 +200,7 @@ pub fn run() -> ExitCode {
])
.plugin(tauri_plugin_single_instance::init(|app, args, _| {
if !args.iter().any(|arg| arg == AUTOSTART_ARG) {
tray::show_main_window(app);
let _ = open_main_window(app);
}
}))
.plugin(tauri_plugin_clipboard_manager::init())
@@ -240,13 +256,12 @@ pub fn run() -> ExitCode {
shutdown,
server: Mutex::new(Some(task)),
exiting: AtomicBool::new(false),
server_addr: address,
});
let window = create_main_window(app.handle(), address)?;
if desktop_settings.silent_start && started_by_autostart {
tracing::info!("silent autostart enabled; keeping the main window hidden");
tracing::info!("silent autostart enabled; starting without the main window");
} else {
window.show()?;
window.set_focus()?;
open_main_window(app.handle())?;
}
tray::create(app)?;
crate::update::signal_ready_if_requested()?;
@@ -262,20 +277,11 @@ pub fn run() -> ExitCode {
};
app.run(|app, event| match event {
RunEvent::WindowEvent {
label,
event: tauri::WindowEvent::CloseRequested { api, .. },
..
} if label == MAIN_WINDOW_LABEL => {
let runtime = app.state::<DesktopRuntime>();
if !runtime.exiting.load(Ordering::Acquire) {
api.prevent_close();
if let Some(window) = app.get_webview_window(MAIN_WINDOW_LABEL) {
let _ = window.hide();
}
}
}
RunEvent::ExitRequested { api, .. } => {
// code 为 None 表示所有窗口已被关闭(轻量模式),阻止退出,
// 转发服务继续在托盘后台运行;code 为 Some 时是显式退出请求。
RunEvent::ExitRequested { code, api, .. } => match code {
None => api.prevent_exit(),
Some(_) => {
let runtime = app.state::<DesktopRuntime>();
if !runtime.exiting.swap(true, Ordering::AcqRel) {
api.prevent_exit();
@@ -289,7 +295,9 @@ pub fn run() -> ExitCode {
Ok(Ok(Err(error))) => {
tracing::error!(%error, "desktop server shutdown failed")
}
Ok(Err(error)) => tracing::error!(%error, "desktop server task failed"),
Ok(Err(error)) => {
tracing::error!(%error, "desktop server task failed")
}
Err(_) => tracing::warn!("desktop server shutdown timed out"),
}
}
@@ -297,11 +305,14 @@ pub fn run() -> ExitCode {
});
}
}
},
#[cfg(target_os = "macos")]
RunEvent::Reopen {
has_visible_windows: false,
..
} => tray::show_main_window(app),
} => {
let _ = open_main_window(app);
}
_ => {}
});
+5
View File
@@ -6,6 +6,11 @@ mod startup;
mod tray;
mod update;
// mimalloc 在释放时主动向操作系统归还内存,避免 glibc 保留页导致
// 关闭窗口后 RSS 无法回落到静默启动水平。
#[global_allocator]
static GLOBAL_ALLOCATOR: mimalloc::MiMalloc = mimalloc::MiMalloc;
pub fn run() -> std::process::ExitCode {
if let Some(exit_code) = update::run_replacement_if_requested() {
return exit_code;
+6 -12
View File
@@ -1,13 +1,13 @@
use tauri::{
menu::{Menu, MenuItem, PredefinedMenuItem},
tray::TrayIconBuilder,
App, AppHandle, Manager,
App,
};
#[cfg(target_os = "windows")]
use tauri::tray::{MouseButton, MouseButtonState, TrayIconEvent};
use crate::desktop::MAIN_WINDOW_LABEL;
use crate::desktop::open_main_window;
const OPEN_MENU_ID: &str = "tray-open";
const QUIT_MENU_ID: &str = "tray-quit";
@@ -24,7 +24,9 @@ pub fn create(app: &mut App) -> tauri::Result<()> {
.menu(&menu)
.show_menu_on_left_click(cfg!(target_os = "macos"))
.on_menu_event(|app, event| match event.id().as_ref() {
OPEN_MENU_ID => show_main_window(app),
OPEN_MENU_ID => {
let _ = open_main_window(app);
}
QUIT_MENU_ID => app.exit(0),
_ => {}
})
@@ -36,7 +38,7 @@ pub fn create(app: &mut App) -> tauri::Result<()> {
..
} = event
{
show_main_window(tray.app_handle());
let _ = open_main_window(tray.app_handle());
}
#[cfg(not(target_os = "windows"))]
@@ -45,11 +47,3 @@ pub fn create(app: &mut App) -> tauri::Result<()> {
.build(app)?;
Ok(())
}
pub fn show_main_window(app: &AppHandle) {
if let Some(window) = app.get_webview_window(MAIN_WINDOW_LABEL) {
let _ = window.unminimize();
let _ = window.show();
let _ = window.set_focus();
}
}