把 mattn/go-sqlite3 换成了 ncruces/go-sqlite3
前者是 CGO 绑定,后者是 WASM 运行时。相关的对比及性能测试可以参考:cvilsmeier/go-sqlite-bench: Benchmarks for Golang SQLite Drivers。
前两天有朋友找到我说要部署一份我的博客系统,让我编译一个 Linux/AMD64 版本(实际上我一直是用的这个版本,只不过是 GitHub Actions 编译到容器里面的,但可以 cp 出来),我再次尝试在 MacOS 上直接 go build,再一次又被 CGO 气死了:没有看到任何 build tags 的 sqlite3.Error 竟然无法编译,找不到定义。
而恰好前几天又正好在群里和雨帆⛵️聊起 sqlite3 的问题,仔细看了前面的对比以及文档,发现 WASM 版本 CGO 版本竟然性能几乎无异,所以就动手切换了。实际上改动的代码只有几行1,因为它俩都是兼容 database/sql 接口标准的。
| 使用的库 | 测试项 | 测试结果 | Delta | ||
|---|---|---|---|---|---|
| 首页 |
| N/A | ||
| 文章 |
| N/A | |||
| 首页 |
| -47% | ||
| 文章 |
| -38% |
“首页”因为几乎没有缓存的原因,相比于“单篇文章”来说性能非常差,在我的预期内。但是从 CGO 换成 WASM 竟然整体性能掉了一半让我震惊。换还是不换呢❓
换,当然要换,对于我这样的小破站来说,即便是只有几百 QPS 的性能也完全没问题。最主要的是:编译速度/跨平台编译容易程度都极大地提高了。还有一点,几百 QPS 显然是另有隐情。
所以我就 profile 了一下 cpu:

好了,知道问题所在了:七年前(至少)写的查“相关文章”的接口没有缓存(大量 IN、OR、!= 语句),瓶颈全在这儿。
加了缓存后,效果改善就“很大”了:
1 2 3 4 5 6 7 8 9 10 |
|
直接起飞到了 4万 QPS。但是仔细观察,发现错误非常多,nginx 的 upstream 不够用了。我直接访问 localhost:
1 2 3 4 5 6 7 8 9 |
|
这次就只有 8000+ 了(全部成功)。
好了,今天的优化至此结束。
测试机器:MacBook Pro 2023 14-inch, M2, 32GB.
再补一下(实时)堆内存占用,压测过后的数值。
| 使用的库 | 内存占用 | QPS |
|---|---|---|
| 29MB | 9378 |
| 39MB | 8176 |
完全可以接受的程度。