DysonFS 调优|什么加载的占位符花了我服务器 30s wall time 计算?!
littlesheepラムです
6/30/2026, 7:30:57 AM169 次阅读

DysonFS 调优|什么加载的占位符花了我服务器 30s wall time 计算?!

然后发现自己的机器太强了基本上看不出来差别

#devlog

你可能会发现在部份图片上传的时候常常会卡在 100% 的进度不动好一段时间。
事实上这其实是小羊在人工审核你的图片啊,要是看到色图就自己吃掉不给其他人看了。

其实 100% 是本地传输内容到服务器完成之后的服务器处理阶段,基本上分为两个部份 analysis(分析)+ optimization(优化)

分析基本上来讲原理很简单,就是读取 EXIF 的数据,图片的长宽之类的,照理来讲不会花太多时间;而优化是将图片生成一个更小的预览版本,会相对花比较多的时间,但是由于是异步进行的所以到也没什么问题。

身为打 OI 出生的臭写代码,一般遇事不决不会打 debugger,而是 std::cout << value << std:endl; 服务器你也打不了 debugger,启一套 perf 工具看火焰图太 overkill 了,所以直接在代码里面计时然后打印出来看看啊。

不看不知道,一看吓一跳!对于一个区区 4.9MB 的 JPEG 格式图片来说:

阶段/事件 最大耗时(ms) 对应文件/消息
analysisDuration 37,905.43 文件 01KWBK...K
totalDuration(整体上传耗时) 42,460.23 同上(包含分析+上传+存储等)
stageDuration(暂存到磁盘) 3,929.12 文件 01KWBK...K 的 staging 阶段
uploadDuration(实际上传耗时) 1,666.72 文件 01KWBK...Q
eventDuration(事件通知耗时) 1.87 文件 01KWBK...Q 的 complete 事件

想着 @a123lsw 看着 100% 的上传进度看了 40s 我就想笑

最开始以为是 EXIF 数据造成的分析延长,但是 EXIF 看到我要动他吓死了,直接提起上诉啊,那咋办呢?写个 benchmark 跑一跑吧!

=== extractExif ===
  WITH EXIF:    open: 77µs  decode: 89µs  walk (53 tags): 0.7µs  total: 167µs
  WITHOUT EXIF: open: 26µs  decode: 1.1ms (EOF error)

=== AnalyzeImage substages ===
  WITH EXIF:
    vips.NewImageFromFile        165ms
    AutoRotate+RemoveMetadata    0.7ms
    blurhash (PNG export+decode) 786ms
    extractExif (full)           0.16ms
  WITHOUT EXIF:
    vips.NewImageFromFile        0.3ms    ← 550x faster
    AutoRotate+RemoveMetadata    0.2ms
    blurhash (PNG export+decode) 762ms
    extractExif (full)           1.0ms   (EOF)

哎呀 怪不得要上诉了 EXIF 酱只能坚持 165ms 呐,真是杂鱼呢❤
事已至此,只能跑跑整个的 benchmark 了。

=== WITH EXIF ===
  vips.NewImageFromFile     531µs      (0.05%)
  AutoRotate                 56µs
  RemoveMetadata             45µs
  ExportPng                 773ms      (67.7%)  ← bottleneck
  png.Decode                208ms      (18.2%)
  blurhash.Encode           160ms      (14.0%)
  os.Open                    60µs
  exif.Decode                73µs
  exif.Walk                  0.8µs
  TOTAL                    1.141s

=== WITHOUT EXIF ===
  vips.NewImageFromFile     256µs
  ExportPng                 766ms      (67.5%)  ← same bottleneck
  png.Decode                207ms
  blurhash.Encode           160ms
  TOTAL                    1.134s

在还原犯罪现场的时候发现一件事,莫名其妙调用了 ExportPng 一次,虽然这不是用来优化的,事情一定不简单 o.0

后来发现 ExportPng 是用来生成 blurhash 的,也就是加载的时候你们看到的模糊占位符,这不对啊,这相当于重新编码了一遍图片,我的压缩到 webp 的优化也大抵就花这么久了。

依照我们数学老师最后教的焚绝,化小不化大,既然 blurhash 本来也没什么有用的信息,直接先把图片压缩 64x 到妈都不认识再看看吧~

CURRENT:  1.133s  (ExportPng 763ms + png.Decode 210ms + blurhash 160ms)
PROPOSED:   35ms   (ExportPng 34ms + png.Decode 0.09ms + blurhash 0.05ms)

一顿操作猛如虎,事实也确实如此,比香港记者跑得还快了现在。但是代价是什么呢…… 嘛不重要了 :maki1+08:

Stage Current Fixed Speedup
NewImageFromFile 311µs 596µs
AutoRotate 52µs 65µs
RemoveMetadata 62µs 51µs
Copy + Resize(64px) 306µs
ExportPng 778.0ms 37.3ms 21x
png.Decode 213.4ms 101µs 2106x
blurhash.Encode(4,3) 162.6ms 47µs 3460x
TOTAL 1.15s 38.5ms 30x

tested on M3 Max, with a 4032x3024 2.2MB JPEG file