网页压图选WebP要等半天?它比JPEG慢了10倍

25 阅读4分钟

周末帮剪片的同事处理一批相机导出的大图,想着 WebP 小就把网页工具里的格式从 JPEG 切到了 WebP。结果每张都要转好一会儿。我第一反应是页面卡死了,差点就去刷新。手一抖滚了下页面才发现滚得动、按钮也点得动,只是结果迟迟不出来。回去一想这事挺有意思:同一张图同一个浏览器换个格式怎么就慢成这样?我回头把 JPEG 和 WebP 的编码时间单独量了一遍。

WebP单次编码比JPEG慢十倍以上

量的机器是我那台 16 GB 内存的 Apple M4 Mac;浏览器是 Chromium 149 开源构建。编码只用浏览器自带的 canvas.toBlob,没接任何第三方库。每张图在 0.30 到 1.00 的质量区间里各编 36 次再取中位数。样本有四张:一张系统自带的 3840×2160 风景照片(830 万像素);两张程序生成的类照片纹理图(1200 万和 2400 万像素),不是拍的;最后一张是 1440×2400 的网页截图。风景照编一次 JPEG 要 21 ms,WebP 要 321 ms。1200 万像素那张编 JPEG 要 37 ms、编 WebP 要 508 ms。2400 万像素那张分别是 74 ms 和 990 ms。编一次 WebP 差不多要一秒。截图小一些:JPEG 要 8 ms、WebP 要 94 ms。四组算下来 WebP 都比 JPEG 慢了十倍以上。

JPEG 与 WebP 单次编码耗时对比

这张图看每组里蓝条和绿条差了多长就行:蓝条是 JPEG,绿条是 WebP。四组的绿条都是蓝条的十几倍长,图越大差距越显眼。截图那组两根条都很短,因为截图像素少,慢十几倍也就一百毫秒不到。

压到指定大小还要连续编码七八次

单张一秒还能忍。麻烦的是很多「压到指定大小」的工具要反复编码好几次才能找到合适的质量。按二分算的话 2400 万像素的图找一轮质量要编 6 到 8 次。我实跑下来 JPEG 找一轮大概 0.5 秒,WebP 要 7.9 到 8.8 秒。我那天等半天就是这么来的:不是一次慢,是一连慢了七八次。

连续编码7次页面也没有卡住

我原本以为编码这么久肯定把页面卡住了。量了才知道不是。编码期间我让页面每 16 毫秒跑一次定时器,记下两次回调之间最长隔了多久。连续做 7 次 WebP 编码花了 7622 ms,定时器最长间隔才 19 ms。页面一直能响应:滚动和点击都不受影响。只有页面上第一次编码会顿一下:单独编一次 WebP 的那回定时器间隔拉到了 177 ms。我猜是浏览器第一次去读画布像素。具体是什么我没拆出来。我还顺手试了把编码挪进 Worker。2400 万像素的图在 Worker 里编 WebP 要 1146 ms,在主线程里编是 1165 ms,几乎没快。挪进去反而让主线程多堵了两百多毫秒。慢是真慢,卡是没卡:等的是编码本身。

急用时两千万像素往上的原图先选JPEG

我手动压图用的是图映 ImgIng(imging.cn/),开在同一台 M4 的 Chromium 里。它的格式按钮上 WebP 和 PNG 标着「即时」,AVIF 标着「按需 WASM」。我猜「即时」的意思是不用额外下载编码器,不是说编码不花时间。它自己压一张要多久我没单独计时。我现在的做法是先看图有多大:几百万像素以内的截图和普通照片直接选 WebP,单次编码多等的那点时间感觉不到。两千万像素往上的相机原图要是急着用就先选 JPEG,不急的话先把尺寸缩下来再转 WebP。WebP 慢归慢,我测过的照片和截图在同样体积下都是 WebP 更清楚一些。值不值得等看你急不急。进度条转着的时候别急着刷新。页面没死,它在干活。