当前位置: 首页 > 科技观察

超级快速的PNG图像解码器!速度提升2.75倍,比libpng大哥更安全

时间:2023-03-20 17:12:21 科技观察

本文经AI新媒体量子比特(公众号ID:QbitAI)授权转载,转载请联系出处。说到PNG,大多数人都不陌生。这种位图格式在图形领域仅次于JPEG。然而,在“解码PNG”这件事上,23年的主流工具是一个叫做libpng的标准库。但最近,一款号称“全球最快的PNG图片解码器”横空出世,速度是“老大哥”的1.22-2.75倍!除了速度上的优势,更重要的是它极其安全。超快的PNG图片解码器不同于libpng使用C语言作为底层,这个PNG图片解码器使用的是Wuffs。Wuffs是一种内存安全的编程语言(以及用该语言编写的标准库),用于安全处理不受信任的文件格式。包括解析、解码和编码图像、音频、视频、字体等。Wuffs不是一种通用的编程语言。它用于编写库,需要将Wuffs与另一种编程语言结合使用的完整程序。尤其是在需要同时考虑性能和安全性的时候。附言。机智的你有没有发现Wuffs其实是WranglingUntrustedFileFormatsSafely的缩写。但它曾经被称为泡芙。至于为什么把Puffs(parsing)改成Wuffs(wrangling),留给你们自己想象吧~那么,解码速度快了2.75倍,怎么做到的呢?Wuffs通过SIMD加速方案、8字节宽输入和复制、位扭曲和zlib将整个图像一次性解压缩到一个大的中间缓冲区中来实现高性能。这种方法取代了以前的一次一行的方法(小块重复压缩)。这种“带走”操作需要更多的中间存储,但可以解码的图像数量也更高。怎么了?我们知道,PNG图像格式的编码/解码是基于以下三个方面:CRC-32和Adler-32两种校验和算法DEFLATE压缩二维滤波Wuffs对其中的每一个步骤都进行了优化。首先,将SIMD加速技术应用于两种校验和算法。SIMD是一种利用一个控制器控制多个处理器,同时对一组数据中的每一个执行相同操作以实现空间并行的技术。其次,Wuffs0.2版具有与zlib库相同的DEFLATE实现,Wuffs0.3版为现代CPU(具有64位未对齐加载和存储)添加了两个重要优化:8字节块输入和8字节区域块输出。DEFLATE是一种同时使用LZ77算法和霍夫曼编码的无损数据压缩算法。对于Wuffs,对于8字节块输入设计,每个内部循环一次读取64位可将DEFLATE微基准测试加速高达1.3倍。虽然8字节块输出设计将复制长度四舍五入为8的倍数,但它可以将DEFLATE微基准提高多达1.48倍。此外,DEFLATE涉及写入目标缓冲区和写入缓冲区边界。(经典的“缓冲区溢出”安全漏洞,类似于从悬崖上逃跑而不是掉进鲨鱼的嘴里)。在这方面,Wuffs使用了类似于libpng的蓝/红双重实现技术。蓝色/红色双重实现技术:快速“蓝色”解压缩(当距离缓冲区末尾至少258字节或更多时)和慢速“红色”解压缩(反之亦然)。用前面悬崖跑的比喻,就是离悬崖边缘远的时候尽量跑得快,离悬崖边缘很近的时候减速刹车。但是同样的技术,为什么Wuffs更快呢?因为它一次将几乎所有内容(例如300×200RGB图像的99%以上的像素)解压缩到一个大的中间缓冲区中,而不是一次只将一行压缩到缓冲区中一个小的、可重复使用的中间缓冲区中。如您所见,现在几乎所有内容都在“蓝色”区域中解码。这本质上比“红色”区域更快。当代码蓝色和红色代码之间交替时,Wuffs还避免了任何指令缓存或分支预测减速。最后,尽管Wuffs和libpng都具有PNG2D过滤的SIMD实现。但是因为libpng将任何自分配的像素行缓冲区对齐到最佳SIMD边界,所以这种对齐会影响SIMD指令的选择和性能。Wuffs对缓冲区对齐的承诺较少,部分原因是Wuffs没有分配内存的能力,但主要是因为zlib压缩需要放弃,例如一次性解压时每行前4个字节的对齐。为什么说它是最安全的呢?与Go或Rust不同,Wuffs的内存安全是在编译时强制执行的,而不是通过干预运行时重新检查来实现的。(ps.运行时安全检查也可能影响性能。)此外,沙箱和多进程架构在处理不受信任的(第三方)PNG图像时可以提供额外的深度防御。上一节介绍的三步优化技术也可以用来修补现有的libpng、Go/RustPNG库等。然后有网友表示很难说Wuffs是否仍然是最快的……但是开发者说起来至少在安全性上,WuffsNo.1没得说。最后,Wuffs0.3.0-beta.1版本刚刚发布,但从目前的功能来看,尚不支持色彩空间或伽马校正。