☰
SiYuan v3.5.5 版本技术解读:mmap 落盘、未引用数据库清理与 I/O 性能优化全解析
2026/10/19 1:27:47 网站建设 项目流程

SiYuan v3.5.5 版本技术解读:mmap 落盘、未引用数据库清理与 I/O 性能优化全解析

【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan

本文基于 SiYuan 官方 v3.5.5 版本变更记录(v3.5.5.md),逐条解读该版本的 23 项功能增强、3 项缺陷修复与 1 项底层重构,并结合内核源码剖析其中三个最有技术含量的改动——基于 mmap 的文档写入、树数据缓存以及未引用数据库(AV)清理——的实现机制,帮助你在自托管部署与二次开发中理解 SiYuan 本地存储 I/O 链路的优化思路。

版本总览

v3.5.5 是一个以"细节改进"为主题的版本,官方概述将其概括为 "This version improves some details"(此版本改进了一些细节)。完整变更清单如下,后文按技术主题分组展开:

功能增强(23 项)

  1. 支持清理未被引用的数据库
  2. 支持移动端浏览器输入工具栏
  3. 改进移动端侧边栏面板滑出的检测
  4. 支持移动端的导出相关设置
  5. 改进批量将图片粘贴到数据库
  6. 光标在移动端代码块内时工具栏将显示增加/减少缩进按钮
  7. 修复移动端块图标消失的问题
  8. 适配 iOS 上苹果的暗色应用图标
  9. 改进 Android 与鸿蒙上软键盘工具栏的弹出
  10. 改进 Ctrl+Shift+T 打开最近关闭文档的功能
  11. 改进在列表项末尾按 Delete 时的编辑结果
  12. 改进在提示块中编辑公式块的体验
  13. 保存查询条件包含搜索方式
  14. 支持通过 HTTPS 提供网络服务
  15. 改进输入法兼容性
  16. 在看板视图中默认创建一个用于分组的选择字段
  17. 改进 Android 与鸿蒙上标题块的复制
  18. 写入文档数据通过 mmap 以减少磁盘写入操作
  19. 改进数据索引以减少磁盘读取操作
  20. 缓存树数据以提升性能并减少磁盘读取操作
  21. 改进集市(插件集市)列表加载
  22. 兼容 HarmonyOS 6.1
  23. 导出包含大量引用的文档时减少内存使用

缺陷修复(3 项):设置键盘快捷键时出现错误、在提示块中编辑列表块后插入位置不正确、改进 AI 继续写入数据库块的行为。

开发重构(1 项):升级至 Electron v39.5.1。

下面按主题深入解读。

本地存储性能优化:mmap 写入、索引改进与树数据缓存

这是本版本技术含金量最高的部分,包含三条相互关联的优化:文档写入走 mmap(对应 issue #16956)、数据索引减少磁盘读(#16958)、树数据缓存(#16961)。三者共同的目标是压缩"编辑—落盘—索引—读取"这条 I/O 主链路上的磁盘操作次数。

文档写入:从"临时文件 + rename"到内存映射原地覆写

SiYuan 的文档(.sy 文件)由内核中的树写出链路负责持久化。v3.5.5 起,写入路径优先采用内存映射(mmap)原地覆写,其核心实现在 mmap.go 的WriteFileByMmap函数中:

// WriteFileByMmap 使用内存映射将 data 原地覆写到 filePath。 // 流程:OpenFile(O_RDWR|O_CREATE) → Truncate 到精确长度 → mmap.Map(RDWR) → // copy 写入 → Flush → Unmap,全程持有 filelock 的进程内互斥锁,避免并发写冲突。 func WriteFileByMmap(filePath string, data []byte) (err error) { f, err := filelock.OpenFile(filePath, os.O_RDWR|os.O_CREATE, 0644) // ... if err = f.Truncate(int64(len(data))); err != nil { /* ... */ } m, err := mmap.Map(f, mmap.RDWR, 0) // ... copy(m, data) if err = m.Flush(); err != nil { /* ... */ } return }

从源码注释可以读出该设计的几个关键取舍:

  • 写入流程:以O_RDWR|O_CREATE打开目标文件 →Truncate到精确长度 →mmap.Map(RDWR)建立读写映射 →copy将数据拷入映射区 →Flush刷盘 →Unmap释放映射;
  • 并发安全:全程持有filelock的进程内互斥锁,避免多个协程对同一文档并发写冲突;
  • I/O 收益:相比传统filelock.WriteFile(临时文件 + rename + fsync),mmap 路径下的copy是纯内存写,不经过 I/O 子系统,只有最终的Flush会产生极少量计入的写操作;
  • 失败回退:mmap 出错时由调用方回退到常规文件写入,保证功能不受影响。

调用方在 tree.go 的WriteTree函数中,完整落盘链路如下(约第 346–390 行):

  1. prepareWriteTree用 Lute 引擎将树渲染为 JSON,并校验笔记本内相对路径、补全updated属性;
  2. 加密笔记本先经encryptData得到密文encData(缓存与比对仍用明文);
  3. 缓存比对:先查cache.GetTreeDataInBox,命中且与待写数据一致则直接跳过落盘;未命中再读盘(加密笔记本需先解密)比对,一致则回填缓存并跳过;
  4. mmap 写入:util.WriteFileByMmap(filePath, encData),失败则回退writeTreeByWriteFile(即filelock.WriteFile);
  5. 大文件超过阈值时向用户推送警告,最后写入缓存cache.SetTreeDataInBox并触发afterWriteTree后处理。

值得强调的是,第 3 步的"缓存未命中再读盘比对、无变更重复写入直接跳过"正是变更日志中"缓存树数据以提升性能并减少磁盘读取操作"(#16961)的落地:缓存实现位于 tree.go 的GetTreeDataInBox/SetTreeDataInBox,以"文档根 ID + 笔记本 ID"为键保存明文树数据,使高频的"打开—无实质改动—保存"场景完全不触盘。

mmap 写入并不只服务于文档:属性视图(数据库)的 JSON 元数据同样走该路径,见 av.go 中util.WriteFileByMmap(avJSONPath, writeData)的调用,即数据库块的结构变更也被纳入同一套低开销落盘机制。

数据索引与磁盘读优化

变更日志中的"改进数据索引以减少磁盘读取操作"(#16958)对应内核的索引队列体系,从源码结构看,索引任务的排队与去重逻辑集中在 index_queue.go 与 queue.go 一带。与树缓存配合后,一次文档保存产生的"写文件 → 解析 → 更新 SQL 索引"链路中,能命中内存缓存的环节将不再重复读盘。

未引用数据库清理:从界面能力到 CLI 命令

"支持清理未被引用的数据库"(#11569)解决的是一个长期存在的维护痛点:文档删除后,其关联的属性视图(AV)JSON 文件可能残留在工作区,成为"孤儿数据库"。

该能力在内核侧由model层提供判定与删除函数(UnusedAttributeViews、RemoveUnusedAttributeView、RemoveUnusedAttributeViews),并暴露为 CLI 子命令,实现在 database.go 中:

var databaseCleanCmd = &cobra.Command{ Use: "clean", Short: "Clean unused databases", RunE: func(cmd *cobra.Command, args []string) error { avID, _ := cmd.Flags().GetString("av") if avID != "" { // 指定单个 AV 清理 model.RemoveUnusedAttributeView(avID) return nil } // 批量清理所有未引用数据库 removed := model.RemoveUnusedAttributeViews() fmt.Printf("%d database(s) cleaned\n", len(removed)) return nil }, }

配套还有只读的unused子命令(model.UnusedAttributeViews(true)列出未引用数据库,支持json输出格式),且两个命令均支持--dry-run模式先预览再执行。对于运维自托管实例的开发者而言,"先unused列出、再clean清理、全程可 dry-run"的三段式操作是一个可验证、可回退的安全流程。

网络服务:支持 HTTPS 发布

"支持通过 HTTPS 提供网络服务"(PR #16930)让 SiYuan 的网络服务(Web 端访问入口)可以直接以 TLS 终结方式对外提供服务,适用于反向代理之外的直连场景,例如配合自签名证书或内网可信证书在局域网/家庭服务器中直接以https://访问。网络服务的启动与路由入口位于 serve.go 与 router.go;从源码结构看,证书配置属于服务端启动参数的一部分,具体字段以当前仓库kernel/conf中的网络配置定义为准。

数据库与视图交互增强

本版本对属性视图相关体验做了三处改进:

  • 批量粘贴图片到数据库(#15128):在表格视图单元格中批量粘贴多张图片时不再丢失或错位,剪贴板侧的图片解析逻辑见 clipboard.go 一带的实现(不同平台有clipboard_darwin.go/clipboard_windows.go的构建标签分离);
  • 看板视图默认分组字段(#16940):新建看板视图时会默认创建一个"选择"类型字段用于列分组。看板布局与分组字段逻辑集中在 layout_kanban.go 与 group.go,从源码结构看,默认字段是在视图初始化阶段注入的,保证用户新建看板即可按列组织行;
  • 保存查询条件包含搜索方式(#16927):搜索面板的"保存查询条件"功能此前不保存查询所用方式(如 SQL 查询/普通搜索),本版本起一并持久化,前端搜索模块位于 search/ 目录。

移动端与跨平台体验

移动端(浏览器 + Android + HarmonyOS)是本次改进数量最多的平台,共 12 项相关变更:

  • 输入与键盘:支持移动端浏览器输入工具栏(#12789);改进 Android 与鸿蒙上软键盘工具栏的弹出时机(#16548);改进整体输入法兼容性(PR #16937),后者主要解决中文输入组合态(composition)期间内容误判问题;
  • 工具栏细节:光标位于移动端代码块内部时,浮动工具栏会显示"增加/减少缩进"按钮(#15381);
  • 交互检测:改进移动端侧边面板滑出(滑出屏幕后唤出)的手势检测(#13915);
  • 显示修复:修复移动端块图标消失(#16074);适配 iOS 上苹果为应用提供的暗色 APP 图标(#16110);
  • 导出设置:移动端设置面板新增导出相关选项(#14757),与桌面端能力对齐;
  • 剪贴板:改进 Android 与鸿蒙上标题块的复制(#16946);
  • 平台兼容:适配 HarmonyOS 6.1(#16974)。移动端前端实现集中在 mobile/ 目录,鸿蒙端内核接入见 harmony/ 目录。

编辑器行为修复

三处编辑器交互与 AI 相关修复值得说明:

  • 列表项末尾 Delete 行为(#16895):修复在列表项末尾按 Delete 键时列表结构合并/删除的结果不符合预期的问题,块编辑核心逻辑位于 editor/ 目录;
  • 提示块内列表插入位置(#16916,缺陷修复):在提示块(callout)中编辑列表块后,新插入块的位置计算错误,已修正;同一提示块场景下公式块的编辑体验也在本版本改进(#16917);
  • AI 续写数据库块(#16944,缺陷修复):改进 AI 在数据库块内继续写入(续写行/单元格)时的定位与插入行为。
  • 快捷键(#16877,缺陷修复):修复在设置中配置键盘快捷键时报错的问题;同时 Ctrl+Shift+T 重新打开最近关闭文档的可靠性得到改进(#16879)。

其他改进与依赖升级

  • 集市列表加载(PR #16965):插件/主题集市列表的加载流程优化,后端集市拉取逻辑位于 bazaar/ 目录;
  • 导出内存占用(#16982):导出包含大量内部引用的文档时减少内存使用,导出主链路见 export.go,通过降低大文档合并导出时的中间对象驻留来缓解峰值内存;
  • Electron 升级:桌面端基础框架升级至 Electron v39.5.1(#16966),依赖版本记录在 package.json 中,属于常规的安全性/稳定性基线跟随。

小结

v3.5.5 虽然是"细节改进"版本,但从内核源码看,其存储链路的变化是实打实的地基工程:WriteFileByMmap+ 树数据缓存 + 索引读优化三者组合,把 SiYuan 的文档写入从"每次全量临时文件写入"变成"先比对、再内存映射覆写"的模式,且通过缓存命中直接省掉读盘比对。对自托管用户而言,本版本可直接收益的功能点包括:HTTPS 网络服务、未引用数据库清理(含 CLIdatabase clean/database unused命令与 dry-run 预览)、看板默认分组字段,以及移动端一揽子输入与工具栏修复。

如需核对本文引用的实现细节,可重点阅读 v3.5.5 官方变更记录(同目录另附 简体中文 与繁体中文版本)以及 mmap 工具实现、树写出链路、CLI 数据库命令 这几个文件。

【免费下载链接】siyuanAn open-source, privacy-first, self-hosted knowledge workspace where humans and AI agents work together 开源、隐私优先、自托管的知识工作空间,让人与智能体在此协作项目地址: https://gitcode.com/GitHub_Trending/si/siyuan

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询