SQLite 默认未开启 WAL ,这会显著限制并发性能。 PlanTodo 是一个计划管理软件,最近我为它的同步服务编写了性能测试,经过实测,仅开启 WAL 就让同步服务的吞吐量便提升至原来的 3 倍, 其实关于 SQLite 性能优化的文章早有珠玉在前,比如 Optimal SQLite settings for Django 和 Optimizing SQLite for servers ,所以本篇文章并没有独创性,只是为了让更多人了解 SQLite 的 性能 以及分享一个真实的性能 测试用例 。 PlanTodo 同步服务性能测试 性能测试分为三个: oo_upload (one user, one device for a user, only upload) ,就是一个用户一台设备仅上传 oo_download 就是仅下载 oo_cross 是上传和下载交错进行 oo_upload 和 oo_download 是为了查看上传和下载场景下的极限性能,是为了将来专门优化时用来参考的。而 oo_cross 则较为贴近真实使用场景:用户的某个设备上传几个更新,另一个设备被触发下载;因此可以拿它计算服务器能承受的用户量。 如果你不想看下面具体的测试数据,这里简单展示了吞吐量的变化: oo_upload ,18027 -> 61682 ,是原来的 3.42 倍 oo_download ,17082 -> 49635 ,是原来的 2.90 倍 oo_cross ,17085 -> 44203 ,是原来的 2.58 倍 一般查询是比写入要快的,因此下载应该比上传快,但 PlanTodo 的同步服务却反了过来,说明有很大的优化空间。 下面是开启 WAL 前的测试数据: + just -f services/sync/justfile headless_oo_upload --less-output ============================================================ Performance Summary for test_oo_upload ============================================================ Requests : 18,027 Failures : 0 Failure Rate : 0.00% Average RT : 78.14 ms P50 : 78 ms P95 : 110 ms P99 : 130 ms Max : 272.81 ms Endpoints ------------------------------------------------------------ POST /v1/sync/delta Requests=18,011 Avg=78.1ms P95=110ms P99=130ms Max=272.8ms POST /v1/clients Requests=8 Avg=76.2ms P95=110ms P99=110ms Max=109.9ms GET /v1/sync/full Requests=8 Avg=57.2ms P95=120ms P99=120ms Max=120.3ms + just -f services/sync/justfile headless_oo_download --less-output ============================================================ Performance Summary for test_oo_download ============================================================ Requests : 17,082 Failures : 0 Failure Rate : 0.00% Average RT : 82.63 ms P50 : 82 ms P95 : 110 ms P99 : 130 ms Max : 370.33 ms Endpoints ------------------------------------------------------------ POST /v1/sync/delta Requests=16 Avg=172.6ms P95=370ms P99=370ms Max=370.3ms GET /v1/sync/delta?cursor=1780662404990&limit=100 Requests=2,087 Avg=83.4ms P95=110ms P99=130ms Max=316.1ms GET /v1/sync/delta?cursor=1780662403978&limit=100 Requests=2,102 Avg=83.3ms P95=110ms P99=130ms Max=325.5ms + just -f services/sync/justfile headless_oo_cross --less-output ============================================================ Performance Summary for test_oo_cross ============================================================ Requests : 17,085 Failures : 0 Failure Rate : 0.00% Average RT : 83.05 ms P50 : 82 ms P95 : 120 ms P99 : 150 ms Max : 245.89 ms Endpoints ------------------------------------------------------------ GET /v1/sync/delta?cursor=1780662760888&limit=100 Requests=1 Avg=245.9ms P95=250ms P99=250ms Max=245.9ms GET /v1/sync/delta?cursor=1780662760900&limit=100 Requests=1 Avg=245.4ms P95=250ms P99=250ms Max=245.4ms GET /v1/sync/delta?cursor=1780662758760&limit=100 Requests=1 Avg=228.2ms P95=230ms P99=230ms Max=228.2ms 下面是 开启 WAL 之后 的测试数据: + just -f services/sync/justfile headless_oo_upload --less-output ============================================================ Performance Summary for test_oo_upload ============================================================ Requests : 61,682 Failures : 0 Failure Rate : 0.00% Average RT : 22.30 ms P50 : 22 ms P95 : 32 ms P99 : 41 ms Max : 74.82 ms Endpoints ------------------------------------------------------------ POST /v1/clients Requests=8 Avg=33.8ms P95=48ms P99=48ms Max=48.1ms POST /v1/sync/delta Requests=61,666 Avg=22.3ms P95=32ms P99=41ms Max=74.8ms GET /v1/sync/full Requests=8 Avg=20.7ms P95=32ms P99=32ms Max=32.5ms + just -f services/sync/justfile headless_oo_download --less-output ============================================================ Performance Summary for test_oo_download ============================================================ Requests : 49,635 Failures : 0 Failure Rate : 0.00% Average RT : 28.03 ms P50 : 28 ms P95 : 38 ms P99 : 46 ms Max : 305.64 ms Endpoints ------------------------------------------------------------ POST /v1/sync/delta Requests=16 Avg=127.0ms P95=310ms P99=310ms Max=305.6ms GET /v1/sync/delta?cursor=1780663066610&limit=100 Requests=6,109 Avg=28.4ms P95=38ms P99=46ms Max=246.0ms GET /v1/sync/delta?cursor=1780663068640&limit=100 Requests=6,064 Avg=28.3ms P95=38ms P99=46ms Max=95.8ms + just -f services/sync/justfile headless_oo_cross --less-output ============================================================ Performance Summary for test_oo_cross ============================================================ Requests : 44,203 Failures : 0 Failure Rate : 0.00% Average RT : 31.80 ms P50 : 28 ms P95 : 45 ms P99 : 150 ms Max : 477.37 ms Endpoints ------------------------------------------------------------ GET /v1/sync/delta?cursor=1780663421960&limit=100 Requests=1 Avg=477.4ms P95=480ms P99=480ms Max=477.4ms GET /v1/sync/delta?cursor=1780663421963&limit=100 Requests=1 Avg=475.9ms P95=480ms P99=480ms Max=475.9ms GET /v1/sync/delta?cursor=1780663421966&limit=100 Requests=1 Avg=475.4ms P95=480ms P99=480ms Max=475.4ms 每个测试只持续了 3 min ,因此数据量很小,在大数据量的情况下,性能可能会下降很多,这个会在将来补充。 在测试 oo_cross 里,3min 处理了 44203 个请求,也就是一秒 245 个。测试其实是不断在重复先上传再下载,而客户端也是上传下载成对出现,因此一秒能处理 122 ( 245 / 2 )台设备的请求,即便因为多用户、多设备带来的其他压力,至少能稳定在一秒 100 个请求。 考虑到,真实使用下,平均要几分钟到十几分钟才会更新一次内容,取 10 分钟一次的话,一个同步服务极限下能支撑 100 x 60 x 10 ,6 万个设备正常使用。 如何开启 WAL 不管是什么 ORM ,开启的方式都是一样的,就是在连接数据库后,执行一次 PRAGMA journal_mode=WAL 。 开启了 WAL 后,在原本的 SQLite 数据库文件那里,会多出两个 .db-shm 、 .db-wal 的文件,可以以此判断是否成功开启。 SQLAlchemy from sqlalchemy import create_engine, event engine = create_engine( DATABASE_URL, echo=False, connect_args={ "timeout": 5, }, ) if engine.dialect.name == "sqlite": @event.listens_for(engine, "connect") def set_sqlite_pragma(dbapi_connection, _): cursor = dbapi_connection.cursor() # cursor.execute("PRAGMA foreign_keys=ON") cursor.execute("PRAGMA journal_mode=WAL") cursor.execute("PRAGMA synchronous=NORMAL") cursor.execute("PRAGMA temp_store=MEMORY") cursor.execute("PRAGMA cache_size=2000") cursor.execute("PRAGMA mmap_size=134217728") cursor.close() PlanTodo 的同步服务就是使用 FastAPI + SQLAlchemy 开发的。由于同步服务的特殊性,这里没有开启外键约束。 Django 在项目的 settings.py 文件里,添加 init_command: DATABASES = { "default": { "ENGINE": "django.db.backends.sqlite3", "NAME": BASE_DIR / "db.sqlite3", "OPTIONS": { "init_command": ( "PRAGMA foreign_keys = ON;" "PRAGMA journal_mode = WAL;" "PRAGMA synchronous = NORMAL;" "PRAGMA busy_timeout = 5000;" "PRAGMA temp_store = MEMORY;" "PRAGMA cache_size = 2000;" "PRAGMA mmap_size = 134217728;" ), }, } } drift 在数据库类的 migration get 方法里,在 beforeOpen 这个回调里增加执行命令: class PtdDatabase extends _$PtdDatabase { // 省略无关代码 @override MigrationStrategy get migration { return MigrationStrategy( beforeOpen: (details) async { // 在每次打开数据库,正式使用之前,执行的命令 await customStatement('PRAGMA journal_mode = WAL'); await customStatement('PRAGMA synchronous = NORMAL'); await customStatement('PRAGMA busy_timeout = 5000'); await customStatement('PRAGMA temp_store = MEMORY'); await customStatement('PRAGMA cache_size = -2000'); }, ); } } 原文链接: https://yanh.tech/2026/06/sqlite-performance-optimization/ 版权声明:本博客所有文章除特別声明外,均为 AhFei 原创,采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 技焉洲 (yanh.tech) 。
[!todo] #一键展开 (不含 NSFW) 点击查看本期内容 (点击了解更多详细信息) [!todo]# NSFW NSFW QAQ Vol.022-NSFW01 (点击了解更多详细信息) NSFW QVQ Vol.022-NSFW02 (点击了解更多详细信息) NSFW QoQ Vol.022-NSFW03 (点击了解更多详细信息) [!todo]# 往期周刊 【摸鱼周刊】Vol.021 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.019 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.019 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.018 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.017 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.016 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.015 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.014 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.013 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.012 一周梗图沙雕乐子图合集 查看更多 1 个帖子 - 1 位参与者 阅读完整话题
我现在设想是codegraph配合todo tree可视化调度。同样热门上那个类comfyui的工作流节点有点用不明白。 但是现在卡在怎么让ai强制使用codegraph的mcp,已经在codex的全局agent和项目agent都声明,任何增删改查的行为都必须通过codegraph的mcp,还试了钩子发挥tool如果没codegraph进行retry(虽然不知道用着对不对)。但是有时候ai大人真的鸟都不鸟我。 7 个帖子 - 7 位参与者 阅读完整话题
但是我简单找了一两款事项提醒或者todolist类的软件,好像都没有在备注里增添这个功能,或者没有直接把网站显示出来。 于是自己vibe了一个,如果你是相关类软件开发者,我觉得可以添加上这个feature,太方便了。 1 个帖子 - 1 位参与者 阅读完整话题
[!todo] #一键展开 (不含 NSFW) 点击查看本期内容 (点击了解更多详细信息) [!todo]# NSFW NSFW QAQ Vol.021-NSFW01 (点击了解更多详细信息) NSFW QVQ Vol.021-NSFW02 (点击了解更多详细信息) NSFW QoQ Vol.021-NSFW03 (点击了解更多详细信息) [!todo]# 往期周刊 【摸鱼周刊】Vol.019 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.019 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.018 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.017 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.016 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.015 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.014 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.013 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.012 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.011 一周梗图沙雕乐子图合集 查看更多 2 个帖子 - 2 位参与者 阅读完整话题
目前可以在这里查看程序介绍和申请加入内测名单 rbtodo.cornradio.org RBTodo 已经撰写了完善的使用文档,这里有详细的程序能力介绍和截图 https://docs.rbtodo.cornradio.org/ 后续正式发布可能考虑免费使用1个月 + 10¥/每年的定价 . 加入内测可以获取v0.99的无限制免费版使用权,会跟随邮件发送。 预计这两周等有50个左右的申请者就发送一个内测版。 2 个帖子 - 1 位参与者 阅读完整话题
Todo已经就位,就等菩萨下凡了 哈哈哈 /Goal已经嗷嗷待哺了 6 个帖子 - 6 位参与者 阅读完整话题
起初是我一直用微软的 todo 应用,然后有一天我不知道我点错了哪里,我一时半会找不到我原来一直停留的 todo 页面了,发现微软的 todo 交互设计有点问题,于是就和 AI 一拍即合,写了一个,已上架 app store ,就叫 Real Todo ,原生制作,畅享丝滑体验 App Store 地址: https://apps.apple.com/cn/app/real-todo-%E6%9E%81%E7%AE%80%E5%BE%85%E5%8A%9E/id6771051099 20 个 Pro 会员 FYTWPW3L7K7RJNLRAP M8PXYPPKNTWR8KA3HL F33R66LAXKFLAR8EWX 46MRW43MM36MPLFM77 6F3JE66WFEXK3MPXML 3XWLKT8PLAF6P7EJY6 YK8HHKA3JXNNMXFXRA 6HEX37XYY3KTFX3FRL 3THXPRP6FNXNJF8744 X7L8PLFRF377TJ3R78 7NWM83T7WRTYJYM637 RH8JJP7H6EYWXLYXYW 668N8AWLRRRHXLMTAM M4PF7YWYXXXRMHAEH4 RPP7FNX8MXTL7AKAHR RYEWWL663HJLRJYJ6Y PTK4H8JHEA6AMXKYKY 6JHNKEMK6YYWFWMMYY 3FW6JTR7XXAWRJ84N8 X4PW4FH44WXPX6H6M6
起初是我一直用微软的 todo 应用,然后有一天我不知道我点错了哪里,我一时半会找不到我原来一直停留的 todo 页面了,发现微软的 todo 交互设计有点问题,于是就和 AI 一拍即合,写了一个,已上架 app store ,就叫 Real Todo ,原生制作,畅享丝滑体验 App Store 地址: https://apps.apple.com/cn/app/real-todo-%E6%9E%81%E7%AE%80%E5%BE%85%E5%8A%9E/id6771051099 20 个 Pro 会员 FYTWPW3L7K7RJNLRAP M8PXYPPKNTWR8KA3HL F33R66LAXKFLAR8EWX 46MRW43MM36MPLFM77 6F3JE66WFEXK3MPXML 3XWLKT8PLAF6P7EJY6 YK8HHKA3JXNNMXFXRA 6HEX37XYY3KTFX3FRL 3THXPRP6FNXNJF8744 X7L8PLFRF377TJ3R78 7NWM83T7WRTYJYM637 RH8JJP7H6EYWXLYXYW 668N8AWLRRRHXLMTAM M4PF7YWYXXXRMHAEH4 RPP7FNX8MXTL7AKAHR RYEWWL663HJLRJYJ6Y PTK4H8JHEA6AMXKYKY 6JHNKEMK6YYWFWMMYY 3FW6JTR7XXAWRJ84N8 X4PW4FH44WXPX6H6M6
[!todo] #一键展开 (不含 NSFW) 点击查看本期内容 (点击了解更多详细信息) [!todo]# NSFW NSFW QAQ Vol.020-NSFW01 (点击了解更多详细信息) NSFW QVQ Vol.020-NSFW02 (点击了解更多详细信息) [!todo]# 往期周刊 【摸鱼周刊】Vol.019 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.018 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.017 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.016 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.015 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.014 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.013 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.012 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.011 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.010 一周梗图沙雕乐子图合集 查看更多 1 个帖子 - 1 位参与者 阅读完整话题
将复杂任务分解,逐步推进。 任务可继承父子计划的关系。 iOS 新上架: https://apps.apple.com/cn/app/plantodo-app/id6764485281 其他平台: https://plantodo.app/zh/
我写了一个 ai bot ,在 telegram 里帮我整理一下 todo ,或者总结群聊对话。有没有什么可以快速部署的工具。比如为不同的项目或者主题,分别部署在不同的群组里
我写了一个 ai bot ,在 telegram 里帮我整理一下 todo ,或者总结群聊对话。有没有什么可以快速部署的工具。比如为不同的项目或者主题,分别部署在不同的群组里
codex现在能解决: (1) 手机端连接(我看有一些bridge工具,但是有老友用过么,更喜欢原生的) (2)关于长期记忆,能把每天的日志记下来,然后回头汇总统计么 (3)可以放在vps上长期跑,可以支持cron job么 1 个帖子 - 1 位参与者 阅读完整话题
群里看到别人发的截图,AI 这么回复… 偷懒还要看一眼当前时间吗 有种说法是:上下文余额不足时,模型会偏向于保守,希望尽快结束任务
群里看到别人发的截图,AI 这么回复… 偷懒还要看一眼当前时间吗 有种说法是:上下文余额不足时,模型会偏向于保守,希望尽快结束任务
群里看到别人发的截图,AI 这么回复… 偷懒还要看一眼当前时间吗 有种说法是:上下文余额不足时,模型会偏向于保守,希望尽快结束任务
[!todo] #一键展开 (不含 NSFW) 点击查看本期内容 (点击了解更多详细信息) [!todo]# NSFW NSFW QAQ Vol.019-NSFW01 (点击了解更多详细信息) NSFW QVQ Vol.019-NSFW02 (点击了解更多详细信息) NSFW QoQ Vol.019-NSFW03 (点击了解更多详细信息) [!todo]# 往期周刊 【摸鱼周刊】Vol.018 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.017 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.016 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.015 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.014 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.013 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.012 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.011 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.010 一周梗图沙雕乐子图合集 【摸鱼周刊】Vol.009 一周梗图沙雕乐子图合集 查看更多 10 个帖子 - 10 位参与者 阅读完整话题
PlanTodo 是一个拥有强大计划系统的待办应用,免费,跨平台,支持多设备使用。全平台的下载链接可以到官网查看: https://plantodo.app/ 。 TestFlight 链接: https://testflight.apple.com/join/MeDAtFqP 。 这有个我准备的用例 https://plantodo.app/static/plantodo_cases.json ,下载后可以在应用设置里全量导入,快速了解功能。 与传统 Todo 应用不同,PlanTodo 将「任务」与「计划」明确分离: 任务:一次性待办事项 计划:可自动生成任务的规则系统 你可以像普通待办应用一样使用它,也可以利用强大的计划系统,自动安排长期事务。 支持常见循环规则: 每天 每周一、周五 每月 1 号 也支持更复杂的高级计划: 每月最后一个周六 跟随其他计划联动触发 在某个计划触发前第 3 天自动创建任务 适用于: 周期性工作安排 健身与学习计划 账单、维护、复盘提醒 长期项目管理 更多计划规则与功能,可在应用内查看。 指南: https://tutorial.plantodo.app/ 。
起因是用番茄Todo遇到要收费的情况,由于囊中羞涩+ai壮胆,准备自己做个Focus Plan的项目,包括网页+小程序+app。ui设计后已经根据ui做了一大部分了, 项目干了一半发现ui设计的网站要收费,我之前就提了一次需求,我现在要设计新的页面,不知道怎么下手了,可恶豆包骗我说免费。 项目做了一半了,下面是半吊子产物,上面生成的ui我又不想重新开始,怎么办佬友们? 25 个帖子 - 16 位参与者 阅读完整话题