From 5b183007a730187de2d7655b15a656dd202e5f28 Mon Sep 17 00:00:00 2001 From: xfy Date: Thu, 16 Jul 2026 10:53:51 +0800 Subject: [PATCH] =?UTF-8?q?perf(server):=20=E7=94=A8=20mimalloc=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E7=B3=BB=E7=BB=9F=E5=85=A8=E5=B1=80=E5=88=86?= =?UTF-8?q?=E9=85=8D=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 多线程高频小对象分配场景下,mimalloc 吞吐显著优于系统 malloc,且对全静态 musl 链接友好(生产 Docker 镜像即 musl 目标)。选 mimalloc 而非 jemalloc: 本项目生产 server 是全静态 musl 二进制,jemalloc 在 musl 上有 pthread_getname_np (musl<1.2.3)/unprefixed-malloc 符号冲突的已知坑。 cfg 双门控(与项目双目标编译约定一致): - feature=server:分配器只服务端二进制需要 - not(wasm32):mimalloc_rust 在 wasm32 上无法编译(Issue #76),前端走默认分配器 mimalloc 声明为 optional + 经 server feature 启用,与 argon2/uuid 等 server-only 依赖同栏位。验证:server native + WASM 双目标编译通过 + clippy 零告警。 musl 目标受本机无 musl-gcc 限制,需 Docker 内构建验证(同 zenwebp 等任何 C 依赖)。 --- AGENTS.md | 2 ++ Cargo.lock | 19 +++++++++++++++++++ Cargo.toml | 5 +++++ src/main.rs | 10 ++++++++++ 4 files changed, 36 insertions(+) diff --git a/AGENTS.md b/AGENTS.md index 9c1daa0..7fd2956 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -129,6 +129,8 @@ Dioxus 0.7 fullstack project with **two independent gates** — the most common **Shared types that compile on both targets**: bridges like `src/tiptap_bridge.rs` and `src/codemirror_bridge.rs` keep shared structs (e.g. `UploadsInFlight`, `SqlSchema`/`SqlTable`) outside cfg gates, while wasm-bindgen externs + `EditorHandle` live in inner `#[cfg(target_arch = "wasm32")] mod wasm`. Similarly `src/sysinfo_sampler.rs` exposes `SystemSnapshot` on both targets but gates the actual sampler + `RwLock` behind `server`. +**Global allocator (mimalloc)**: `src/main.rs` registers `#[global_allocator] static GLOBAL: mimalloc::MiMalloc` gated with `#[cfg(all(feature = "server", not(target_arch = "wasm32")))]`. Both gates are load-bearing: `mimalloc` is `optional = true` enabled via the `server` feature, and the `mimalloc_rust` crate does not compile on `wasm32` (Issue #76), so the WASM frontend must fall back to the default allocator. Do not delete either cfg — removing the `not(wasm32)` gate breaks the frontend bundle, removing the `server` gate pulls mimalloc into the WASM target. Chosen over jemalloc because the production server is a fully-static musl binary (Dockerfile), and jemalloc has known musl build pitfalls (`pthread_getname_np` for musl <1.2.3, `unprefixed-malloc` symbol conflicts); mimalloc links cleanly into musl/glibc/FreeBSD. + ## Dual API Architecture The server exposes two distinct API patterns: diff --git a/Cargo.lock b/Cargo.lock index 8ffc017..5272352 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2644,6 +2644,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.18" @@ -2868,6 +2877,15 @@ dependencies = [ "libc", ] +[[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" @@ -5496,6 +5514,7 @@ dependencies = [ "js-sys", "lol_html", "md-5 0.10.6", + "mimalloc", "moka", "pinyin", "pulldown-cmark", diff --git a/Cargo.toml b/Cargo.toml index 19a47e7..57d212d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,10 @@ bollard = { version = "0.21", optional = true } # 把 mpsc::Receiver 包成 Stream,供 axum SSE handler 使用。 # axum::response::sse::{Sse,KeepAlive,Event} 随 axum 0.8 自带,无需额外 dep。 tokio-stream = { version = "0.1", features = ["sync"], optional = true } +# 全局分配器:用 mimalloc 替换系统 malloc。多线程高频小对象分配吞吐显著提升, +# 且对全静态 musl 链接友好(生产 Docker 镜像即 musl 目标)。 +# server-only:经 server feature 启用;WASM 前端构建不编译(见 main.rs cfg 门控)。 +mimalloc = { version = "0.1", optional = true } [target.'cfg(target_arch = "wasm32")'.dependencies] web-sys = { version = "0.3", features = ["Document", "Window", "Storage", "Element", "HtmlElement", "DomTokenList", "MediaQueryList", "HtmlImageElement", "MouseEvent", "KeyboardEvent", "Node", "EventTarget", "Navigator", "File", "FileList", "FormData", "Request", "RequestInit", "Response", "Headers", "ClipboardEvent", "DataTransfer", "HtmlInputElement", "EventSource", "MessageEvent"] } @@ -114,4 +118,5 @@ server = [ "dep:bytes", "dep:bollard", "dep:tokio-stream", + "dep:mimalloc", ] diff --git a/src/main.rs b/src/main.rs index 5f8e0cc..bdf1280 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,16 @@ //! 当未启用 `server` feature(例如编译为 WASM 前端)时, //! 仅调用 `dioxus::launch` 启动客户端应用。 +// 全局内存分配器:mimalloc。 +// 多线程高频小对象分配场景下吞吐显著优于系统 malloc,且对全静态 musl 链接友好。 +// cfg 门控(与项目「双目标编译」约定一致): +// - feature = "server":分配器只服务端二进制需要。 +// - not(wasm32):mimalloc_rust 在 wasm32 上无法编译(mimalloc_rust Issue #76), +// WASM 前端走默认分配器。两个门控同时满足才注册。 +#[cfg(all(feature = "server", not(target_arch = "wasm32")))] +#[global_allocator] +static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; + // 业务模块 mod api; mod auth;