关于思源同步为啥这么慢的探究

本贴最后更新于 291 天前,其中的信息可能已经时异事殊

太长不看:

  1. 扫盘建立快照不够高效,占比 10%
  2. 网络条件拉跨,占比 10-100%(假如你家网速正常就 10%,不正常直接断了,影响算 100% 是没问题吧trollface
  3. 同步有锁,必须交替进行,占比 30%
  4. web 上传对小文件极不友好,占比 50%

关于一些前置的讨论可以看看 Issue #12246 · siyuan-note/siyuan ,我在这里研究了下 obsidian 的 livesync 插件与思源同步机制的差异,试图搞清楚,为啥都能使用 S3 作为同步中介,livesync 可以做到实时同步,而思源则有明显的卡顿感。

一个反直觉的观点是,思源的快照机制并不慢,至少不是同步慢的最主要问题。以下是测试出来的快照建立时间于同步时间之间的差异:

  • 日记编辑 0.75s,未同步
  • 主题更新(22 个文件,2m 数据量)0.86s,同步时间 3s
  • 安装插件(650 个文件,20m 数据量)3.36s,同步时间 94s
  • 删除插件(删除 650 个文件,20mb 数据)0.86s,同步时间 14s

以上都是先建立快照,再进行同步的操作,换而言之,同步的时间已经是去除快照建立的时间了,但是还是可以看出相对于快照操作是很慢的。

因此同步慢的的最大根源就是同步加锁……而已吗?

直到今天之前,我都是这个观点,但我忽然想到,同步加锁只是会影响到另一端同步并下载云端内容的速度,理论上不会影响到我这一端上传的速度,或许还要严格评估一下 web io 对于同步速度的影响。因此我直接在本地搭建了一个 docker minio,新开了一个库作为测试。我同时把我主笔记库的数据复制过来了,总共是 800m 的大小,6500 个文件。

我阅读了 dejavu 的代码,发现它里面有对同时上传文件数的限制。我合理的怀疑这就是问题的根源。于是,我拉到本地,进行修改,将同时上传、下载文件数的限制,也是 NewPoolWithFunc 的 poolSize 全拉高了 10 倍,重新打包思源的 kernel,进行测试。以上所有操作都是基于思源是个开源软件,所有,哎,就是能改着玩!

在我进行修改之前,使用本地的 minio 进行全库上传的耗时是 440s,那么,你觉得我修改后的耗时是多少呢?

还是 436s!

这少掉的 4s,完全可以被认为就是一个误差而已,因此可以说,dejavu 里对同时上传文件大小的限制,根本就不是同步慢的原因。

我尝试绕过思源,直接通过 minio 的 webui 上传,时间相差无几。

接着,我做了另一种尝试,使用 restic 进行备份,然后直接通过 webui 上传。备份同样的内容,思源的同步机制总共生成了 13,062 个文件,259 个文件夹,而 restic 则是 48 个文件,261 个文件夹。

最后,restic 的上传时间为 10s。

在查看日志中发现,minio 的同时上传速度哪怕在本地也只能做到每秒 40 左右的文件。

作为测试,我尝试使用官方的上传机制,这次就更慢了,每秒只能上传 16 个文件。而且甚至因为同时上传等待时间过长,还给我返回了 time out 报错。

因此,问题的根源似乎很清楚了:思源扫盘建立快照当然可以进步,但进步空间不大。改善云端同步协作机制、实现无锁同步,以及改变思源的快照分片机制,才是根本解决方案。

那么,古尔丹,代价是什么呢?

代价就是,从此思源的增量下载能力可能大大减弱,可能你下载一个快照,就得把整个库下载回来,因为现在一个数据分块对应了多个实际的文件,你只能一起下载回来再拆分。

这里,我就不得不感慨,省空间换时间,还是省时间换空间,依然、并且永远,是一个值得考虑的问题啊。

  • 思源笔记

    思源笔记是一款隐私优先的个人知识管理系统,支持完全离线使用,同时也支持端到端加密同步。

    融合块、大纲和双向链接,重构你的思维。

    25771 引用 • 106684 回帖

相关帖子

优质回帖
  • tianzhongs 1 赞同

    目前的优化的话,我能想到的就是类似于 Duplicati(某备份工具),他也是增量备份,他的逻辑是

    1. 第一个文件:把元数据的一些映射关系做了信息映射;
    2. 别的文件就是加密后的元数据,同样也是进行了分片,但是他多了一个步骤,就是

    压缩,我觉得这个压缩很有搞头

    1. 每次增量备份,只多备份新的修改的元数据对照和压缩的元数据

    他这个备份工具也支持加密,也是一样的,我个人体验同步速度算快的,毕竟他压缩的大小能指定,比如说 650MB(CD 大小),元数据足够大的话,就会有很多的 650MB 的压缩包,上传起来比思源现在的上传小文件肯定会快很多;

    然后就是映射关系,他本地也有一个数据库,保存的是映射关系和日志,相当于是缓存,可以删因为云端也有,这种同步的话,除了第一次同步这个日志数据库慢点,其余时间都比思源快很多。

    加密上传后的的目录:能看到精简了很多

    image.png

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • zxhd86

    这个可能不是你觉得自己打几个字就真的是几个字了,你得看看实际数据块的数量。实际上真正的打几个字的场景就是开了同步感知进行交替同步,目前我测试的延迟就是 6s 左右。你可能得看看内核日志,确定到底主要在干啥了。

    2 回复
  • 其他回帖
  • zxhd86

    我再说的通俗一点,如果你家里宽带有 10000 兆的带宽,那么你下载腾讯 s3 的速度就是一万兆,你个人就算是硬盘提供得了这么大的速度吗?详情见这里,https://doc.fincloud.tencent.cn/tcloud/Storage/COS/845813/uploaddownloadfaq
    对象存储的性能和带宽不上限,只按量,远超你自己局域网运行一个 docker 的性能

    对象储存对于少量大文件的带宽确实能跑满,但是大量小文件就不太行了。这个我已经在腾讯云上尝试过了,参照上面的记录,golang 并发上传数设为 640,但是每秒上传文件数他就是有上限的,腾讯云也只能达到每秒 20 个,目前看来,对于小文件,还是 minio 在本地是比较快。

    如果你测试出更好的数据,可以跟我说一下怎么写,我也可以改进下 siyuan 这方面的代码。

    我说了没有那么好的事情,即自由又稳定,况且,又不是没有解决方案,只需要把附件这种不会频繁变动的内容单独走另一个单独的上传信息通道就好了,而不是放到高频索引里面再扫一遍

    可是实际上外部变动主要就是改附件啊,单纯思源本身的笔记文件反而不太会被改,因为其他软件读不懂……

    至少 ob 可以直接知道该同步哪一个 md 文件,思源可以在操作后马上知道该同步哪一个 sy 文件吗?倘若能,为什么要去扫盘?难道是因为我改了一个 sy 文件,每一次都要扫库看看我有没有改其他文件吗?那为什么不一直扫,万一我改了其他的文件但是没该文档,岂不是没有办法了,只能等我改文档的时候再帮我检测一下?这个思路倒是可以理解了。我是真的觉得,和用户的操作一块进行,监听哪些文件发生更改,然后没有中间服务商直接同步哪些文件,都比现在快。

    我倒是没有否认 ob livesync 建立快照速度更快,更有优越性,只不过 golang 上没有太好可用的包。

    我知道你不停的强调建立一个快照或者索引有多快,但是,在我用的过程中,建立快照并不是卡我的原因,原因是这个快照索引本身就是没有时效性的,不可靠的,所以它不是建立完就没事了,他需要下载下来,然后解析,然后一个个核对,我的同步大部分时间就是花在这个核对索引上,一直在校验索引,少则校验 5-6s,多则半分钟,3.10 版本有时候校验索引都会卡死,扫盘建立的索引,终究还是要扫盘去核对

    此索引非彼索引啊,这里有两个概念的索引,siyuan sqlite 里的索引和快照 dejavu 使用的文档索引。思源懒得判断文档变化情况选择全部校验一遍来重建 sqlite 确实是懒政情况了,但是这跟同步的索引和快照完全是两回事啊。解决问题终究还是要一个个来的。

    局域网内客户端是可以互相沟通同步的,每个客户端都具有与储存器之间的完整的中间件

    我觉得对等点本身就是一个服务端了吧……硬要这么说,思源也可以内部塞一个 webdav 或 s3 实现,然后直接通过局域网发现协议互相找到端口,进行同步。但是这种情况下思源自己就成为服务端了,这跟思源作为伺服的区别有多大呢?

    1 回复
  • 然后就是关于你提供的代码定位,我当然可以跟着你看代码,可以看到,光是监听就写了

    plugin.registerEvent(plugin.app.vault.on("modify", this.watchVaultChange)); plugin.registerEvent(plugin.app.vault.on("delete", this.watchVaultDelete)); plugin.registerEvent(plugin.app.vault.on("rename", this.watchVaultRename)); plugin.registerEvent(plugin.app.vault.on("create", this.watchVaultCreate)); //@ts-ignore : Internal API plugin.registerEvent(plugin.app.vault.on("raw", this.watchVaultRawEvents));

    五个,每一个事件不只是一个触发器来触发进行扫盘索引,而是拥有具体的返回对象,例如

    watchVaultChange(file: TAbstractFile, ctx?: any) { this.appendQueue([{ type: "CHANGED", file }], ctx); }

    通过将文件的修改事件封装成一个对象,这个方法能够为后续的处理提供结构化的数据,这至少是一种基本的处理,至少是和操作挂钩了,返回校验也不需要重新牵一发而动全身

    其他的我就不细看了,要休息

    1 回复
  • tianzhongs

    随便说两点,第一,你拿 ob 的 livesync 实时同步来比较,并不恰当,因为 livesync 的同步是挂在服务器上,其本质就跟你部署在 docker 上,访问网页应用类似;

    当然,这并不是思源同步慢的真正原因,真正的原因是:

    1. 可能存在线程或者文件并行同步的数量限制;
    2. 加密,你应该考虑思源是加密了的,也就是说存在类似于 Cryptomator 那样的加密措施,导致文件和文件夹众多,可以直接在对象存储平台查看加密后的文件夹就会发现非常多image.png
    3. 文件和文件夹的深度和数量都会极其影响同步、复制等速度,这个使用过 npm 以及复制 jar 包的同学应该都深有体会

    我目前每次同步的速度大概在 3s 左右,如果有重大改变,可能会在十几秒左右,但是我觉得这个同步速度其实还好,因为有个 30s 自动同步的机制,所以我平时也很少手动同步,但是每次启动的时候的加载才是让我头痛的,每次都要等待封面,这个有点无语。

    你如果非要对比的话,应该对标是 ob 的 remotely save 插件,记得加上加密,其次,ob 的该插件似乎不会分割文件,所以还是有一定的区别,但是会比你说的 livesync 更接近对比效果。

    如果说解决的话,你要么就不用思源的官方同步,直接用三方同步工具同步 data 文件夹,这个也是可以的,我尝试过,只是不优雅。或者说用 docker 部署,这个优雅,但是只能用浏览器访问。

    1 回复
  • 查看全部回帖

推荐标签 标签

  • golang

    Go 语言是 Google 推出的一种全新的编程语言,可以在不损失应用程序性能的情况下降低代码的复杂性。谷歌首席软件工程师罗布派克(Rob Pike)说:我们之所以开发 Go,是因为过去 10 多年间软件开发的难度令人沮丧。Go 是谷歌 2009 发布的第二款编程语言。

    499 引用 • 1395 回帖 • 244 关注
  • Postman

    Postman 是一款简单好用的 HTTP API 调试工具。

    4 引用 • 3 回帖 • 3 关注
  • GitLab

    GitLab 是利用 Ruby 一个开源的版本管理系统,实现一个自托管的 Git 项目仓库,可通过 Web 界面操作公开或私有项目。

    46 引用 • 72 回帖
  • 创业

    你比 99% 的人都优秀么?

    82 引用 • 1395 回帖
  • WiFiDog

    WiFiDog 是一套开源的无线热点认证管理工具,主要功能包括:位置相关的内容递送;用户认证和授权;集中式网络监控。

    1 引用 • 7 回帖 • 611 关注
  • 开源中国

    开源中国是目前中国最大的开源技术社区。传播开源的理念,推广开源项目,为 IT 开发者提供了一个发现、使用、并交流开源技术的平台。目前开源中国社区已收录超过两万款开源软件。

    7 引用 • 86 回帖
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    43 引用 • 44 回帖
  • BookxNote

    BookxNote 是一款全新的电子书学习工具,助力您的学习与思考,让您的大脑更高效的记忆。

    笔记整理交给我,一心只读圣贤书。

    1 引用 • 1 回帖 • 1 关注
  • RIP

    愿逝者安息!

    8 引用 • 92 回帖 • 403 关注
  • uTools

    uTools 是一个极简、插件化、跨平台的现代桌面软件。通过自由选配丰富的插件,打造你得心应手的工具集合。

    7 引用 • 27 回帖
  • Flutter

    Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作,它正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。

    39 引用 • 92 回帖 • 4 关注
  • 导航

    各种网址链接、内容导航。

    44 引用 • 177 回帖 • 1 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 283 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    209 引用 • 2040 回帖 • 4 关注
  • 印象笔记
    3 引用 • 16 回帖 • 1 关注
  • 互联网

    互联网(Internet),又称网际网络,或音译因特网、英特网。互联网始于 1969 年美国的阿帕网,是网络与网络之间所串连成的庞大网络,这些网络以一组通用的协议相连,形成逻辑上的单一巨大国际网络。

    98 引用 • 367 回帖
  • AWS
    11 引用 • 28 回帖 • 3 关注
  • 小说

    小说是以刻画人物形象为中心,通过完整的故事情节和环境描写来反映社会生活的文学体裁。

    32 引用 • 108 回帖
  • BAE

    百度应用引擎(Baidu App Engine)提供了 PHP、Java、Python 的执行环境,以及云存储、消息服务、云数据库等全面的云服务。它可以让开发者实现自动地部署和管理应用,并且提供动态扩容和负载均衡的运行环境,让开发者不用考虑高成本的运维工作,只需专注于业务逻辑,大大降低了开发者学习和迁移的成本。

    19 引用 • 75 回帖 • 677 关注
  • Follow
    4 引用 • 12 回帖 • 4 关注
  • DNSPod

    DNSPod 建立于 2006 年 3 月份,是一款免费智能 DNS 产品。 DNSPod 可以为同时有电信、网通、教育网服务器的网站提供智能的解析,让电信用户访问电信的服务器,网通的用户访问网通的服务器,教育网的用户访问教育网的服务器,达到互联互通的效果。

    6 引用 • 26 回帖 • 534 关注
  • 面试

    面试造航母,上班拧螺丝。多面试,少加班。

    326 引用 • 1395 回帖
  • Sublime

    Sublime Text 是一款可以用来写代码、写文章的文本编辑器。支持代码高亮、自动完成,还支持通过插件进行扩展。

    10 引用 • 5 回帖
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 199 关注
  • HBase

    HBase 是一个分布式的、面向列的开源数据库,该技术来源于 Fay Chang 所撰写的 Google 论文 “Bigtable:一个结构化数据的分布式存储系统”。就像 Bigtable 利用了 Google 文件系统所提供的分布式数据存储一样,HBase 在 Hadoop 之上提供了类似于 Bigtable 的能力。

    17 引用 • 6 回帖 • 63 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    246 引用 • 1338 回帖