Skip to content

perf(deployer): release memory to OS after batch dictionary compilation on glibc - #1200

Open
EasternLi wants to merge 2 commits into
rime:masterfrom
EasternLi:master
Open

perf(deployer): release memory to OS after batch dictionary compilation on glibc#1200
EasternLi wants to merge 2 commits into
rime:masterfrom
EasternLi:master

Conversation

@EasternLi

@EasternLi EasternLi commented Jul 26, 2026

Copy link
Copy Markdown

Pull request

Issue tracker

Manual test

  • Done

@lotem

lotem commented Jul 27, 2026

Copy link
Copy Markdown
Member

我拜讀了 https://www.reddit.com/r/C_Programming/comments/13dn8d7/is_malloc_trim_safe_to_use/

不太看好這項修改。

若系統的內存管理策略便是如此、不急回收,用家爲何如此執着於統計數字?
只要沒有內存泄漏,就無須擔心。

@EasternLi

Copy link
Copy Markdown
Author

我拜讀了 https://www.reddit.com/r/C_Programming/comments/13dn8d7/is_malloc_trim_safe_to_use/

不太看好這項修改。

若系統的內存管理策略便是如此、不急回收,用家爲何如此執着於統計數字? 只要沒有內存泄漏,就無須擔心。

因为实际表现不是“不急回收”,而是“不再回收”,看起来与一次性的“内存泄漏”并无区别。
而当系统的内存紧张时,这部分内存还会被交换到硬盘上,我稍微有点担忧硬件寿命。

@lotem

lotem commented Jul 28, 2026

Copy link
Copy Markdown
Member

因为实际表现不是“不急回收”,而是“不再回收”,看起来与一次性的“内存泄漏”并无区别。
而当系统的内存紧张时,这部分内存还会被交换到硬盘上,我稍微有点担忧硬件寿命。

這是推測,還是有實證呢。

聽上去 glibc 的自動內存回收機制完全沒有正常工作。
若果真如此,glibc 這樣的基礎程序庫,難道不打算解決問題嗎?難道需要每個應用自己處理?
太不合常理了。

我選擇謹慎。

如果問題不出在 glibc——很有可能不是,不是說 macOS 也如此表現麼,那這個修改就屬於 hack 沒有找到真正的病因。

@EasternLi

Copy link
Copy Markdown
Author

這是推測,還是有實證呢。

在我环境上确实如此。我使用的词典是 https://github.com/iDvel/rime-ice + https://github.com/felixonmars/fcitx5-pinyin-zhwiki + https://github.com/outloudvi/mw2fcitx 。词典较大所以被占的内存也偏多,经常会注意到 fcitx5 进程占用的 RSS/SWAP 超过 1G 。

聽上去 glibc 的自動內存回收機制完全沒有正常工作。 若果真如此,glibc 這樣的基礎程序庫,難道不打算解決問題嗎?難道需要每個應用自己處理? 太不合常理了。

我選擇謹慎。

如果問題不出在 glibc——很有可能不是,不是說 macOS 也如此表現麼,那這個修改就屬於 hack 沒有找到真正的病因。

我不太清楚 macOS 上的具体行为,也许系统内存紧张时就会自动释放? 这里声称 macOS 上的 malloc_zone_pressure_relief 函数也可以强制释放内存回 OS,这里则声称该函数与 memory pressure handlers 有关。

malloc_trim 能释放这部分内存来看,我觉得 librime 本身没有真正的问题。也许是有高峰值内存的常驻进程比较少,恰好碰到了 glibc 的低性能场景?调查到 glibc 有这个 bug,症状类似,不清楚原因是否相同。邮件列表里也提到有些情况可能需要定期 malloc_trim。 ¯_(ツ)_/¯

@ksqsf

ksqsf commented Jul 28, 2026

Copy link
Copy Markdown
Member

malloc_trim 应该是 safe 的,不过我的顾虑是这个修复或许不应该进入 librime,因为它会引入一个符号依赖。设想有人用 glibc 编译了 librime,然后使用 LD_PRELOAD 换成了另一个分配器,但这个分配器里没有 malloc_trim,就会导致程序无法正常运行。malloc_trim 本身也并未被声明为弱符号。

如果要在上游实现,或许可以用 dlsym。

@lotem

lotem commented Jul 29, 2026

Copy link
Copy Markdown
Member

要不先在 fcitx-rime 裏面折騰,看看效果?

@EasternLi

Copy link
Copy Markdown
Author

malloc_trim 应该是 safe 的,不过我的顾虑是这个修复或许不应该进入 librime,因为它会引入一个符号依赖。设想有人用 glibc 编译了 librime,然后使用 LD_PRELOAD 换成了另一个分配器,但这个分配器里没有 malloc_trim,就会导致程序无法正常运行。malloc_trim 本身也并未被声明为弱符号。

如果要在上游实现,或许可以用 dlsym。

LD_PRELOAD 替换没有 malloc_trim 的分配器的话,malloc_trim 这个函数会 fallback 回 glibc 实现。我本地测试 LD_PRELOAD=/usr/lib/libmimalloc.so 可以正常运行,不过我也没法保证混用两个分配器不会出问题,所以还是加个检测。

实在没找到直接的检测方法,就用 dladdr 尽可能保守地检测 mallocmalloc_trim 同源了。通常的 glibc librime 各自都是动态库,LD_PRELOAD 替换别的动态库 或是 可执行文件自己带了分配器 的情况检测是没问题的。极端的 librime 被静态链接到没开位置无关的可执行程序 (会触发 dladdr man 里的那个 bug) 或是 和 glibc 与其他分配器都静态链接到可执行程序 也都会因保守策略跳过。

@EasternLi

Copy link
Copy Markdown
Author

要不先在 fcitx-rime 裏面折騰,看看效果?

合到 fcitx-rime 里的话,跟内存消耗的诱因词典编译有点分离了。
至于效果我本地可以验证,需要额外验证的话应该也不需要合进去?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants