Skip to main content

pagesift_sys/
lib.rs

1//! 进程级调优。整个 pagesift 只有这里有 unsafe:调用 glibc 的 `mallopt`。
2//!
3//! 只应该由 pagesift 自己的可执行程序调用;Python、Node 绑定跑在别人的进程里,
4//! 不能替宿主改分配器参数。
5
6#![deny(unsafe_code)]
7
8/// 固定 glibc 的 mmap 阈值。
9///
10/// glibc 默认会在释放大块内存后把 mmap 阈值调高(最高 32 MB),之后页面大小的缓冲区
11/// (几百 KB 到几 MB 的 HTML、DOM、Markdown)都改从堆里分配,用完不还给系统。
12/// 并发爬取时 RSS 因此是实际使用量的两倍多。固定在 256 KB 后这些块用完立即归还:
13/// 本地 20 站点爬取的峰值 RSS 从 188 MB 降到约 75 MB,CPU 多约 8%。
14/// 非 glibc 平台什么也不做。
15pub fn tune_allocator() {
16    #[cfg(all(target_os = "linux", target_env = "gnu"))]
17    {
18        /// 显式设置后 glibc 不再动态调整阈值。
19        const MMAP_THRESHOLD: libc::c_int = 256 * 1024;
20        const ARENA_MAX: libc::c_int = 4;
21        // SAFETY: mallopt 只修改分配器参数,任何时候调用都安全;返回 0 表示参数不被接受,忽略即可。
22        #[allow(unsafe_code)]
23        unsafe {
24            libc::mallopt(libc::M_MMAP_THRESHOLD, MMAP_THRESHOLD);
25            libc::mallopt(libc::M_ARENA_MAX, ARENA_MAX);
26        }
27    }
28}
29
30/// 显式通知 glibc 分配器向操作系统释放无用堆页面。
31pub fn trim_memory() {
32    #[cfg(all(target_os = "linux", target_env = "gnu"))]
33    {
34        #[allow(unsafe_code)]
35        unsafe {
36            libc::malloc_trim(0);
37        }
38    }
39}