QOI 圖片無損壓縮演算法

Hacker News Daily 上看到「Lossless Image Compression in O(n) Time」這篇,作者丟出了一個圖片的無損壓縮演算法,壓縮與解壓縮的速度超快,但壓縮率又不輸 PNG 太多,在 Hacker News 上的討論也可以看一下:「QOI: Lossless Image Compression in O(n) Time (phoboslab.org)」。

裡面有提到在遊戲產業常用到的 stb_image.h

Yes, stb_image saved us all from the pains of dealing with libpng and is therefore used in countless games and apps. A while ago I aimed to do the same for video with pl_mpeg, with some success.

作者的簡介也可以看到他的主業也在遊戲這塊:

My name is Dominic Szablewski. I build games, experiment with JavaScript and occasionally tinker with low-level C.

圖片的無損壓縮與解壓縮算是遊戲創作者蠻常用到的功能,所以他想要看看這塊有沒有機會有更好的工具,於是他就用了四個很簡單的演算法幹完了 QOI (然後發現效果很讚):

  • A run of the previous pixel
  • An index into a previously seen pixel
  • The difference to the previous pixel
  • Full rgba values

其實從 Hacker News 的討論也可以看到這組演算法也常被拿出來在現代的壓縮演算法使用,所以雖然作者自稱不是 compression guy,但他用的演算法其實蠻專業的...

然後挑 single thread 主要是可以避免 threading 的複雜度以及 overhead,在「QOI Benchmark Results」這頁可以看到,無論是什麼類型的檔案,壓縮與解壓縮的速度都相當漂亮,而且壓縮率又沒有差 libpng 太多。

而且作者自己有提到,還沒用到 SIMD 指令集加速,這樣猜測應該還有不少空間...

PostgreSQL 14 支援的 LZ4 壓縮

Hacker News 上看到 PostgreSQL 14 新支援的 LZ4 壓縮:「The LZ4 introduced in PostgreSQL 14 provides faster compression (fastware.com)」,在討論裡面反而有提到可以用 ZFS 的壓縮,這樣所有的資料 (包括 index) 都可以被壓縮:

If you are using ZFS, I strongly recommend using LZ4 or ZSTD compression with PostgreSQL. Performance is still awesome. On average I get 2x compressionratio with LZ4 and 4x with ZSTD.

With this, you are compressing everything, not just columns. And ZFS has dynamic block sizes which works really great together with compression. For example a 8kb PostgreSQL page, may be stored as a 1kb compressed block on disk.

而且通常開了壓縮後,整機的效率都會比較好。主要是因為資料庫的資料夠大時 (超過記憶體大小) 通常效能會先卡在 Disk I/O 的部份,這時候 CPU 會太閒;如果挑個輕量的壓縮演算法的話,雖然 CPU 使用率會拉高一些,但會大幅降低 Disk I/O 的量,在很多情況下就會提昇效能...

上面提到主要是 OLTP 的情況下,如果是在 OLAP 的場景下就更明顯了,基本上大家都是預設開著壓縮在處理所有資料。

另外在很多 RPC 類的系統也有類似的現象,資料傳輸量已經太大會超過 Network I/O 可以提供的量,這時候導入一些輕量的壓縮演算法就能大幅提昇系統效能。

以前有讀到一些壓縮演算法的比較,像是先前有翻到的「Evaluating Database Compression Methods: Update」,針對演算法的部份分析,裡面最後一張圖可以看到比較:

從比較圖可以穿來 Snappy 後來被 LZ4 淘汰掉,主要就是 LZ4 的壓縮率比較好,壓與解的速度又比較快,沒有理由繼續 Snappy。

另外 Zstandard 也逐步在淘汰 gzipzlib 類的壓縮,不過畢竟 gzip 與 zlib 的歷史真的太久,這邊淘汰的速度不快...

用在 IoT 裝置上的壓縮演算法 Heatshrink

在「Heatshrink – An ultra-lightweight compression library for embedded systems」這邊看到的演算法 Hearshrink,可以看到主打是在記憶體的用量受限的環境下壓縮。

在 2013 年的資料就有壓縮率的比較了:「heatshrink: An Embedded Data Compression Library」。

像是目前常被拿來使用的 ESP32 就只有 320KB 記憶體,gzip 就明顯太肥大了,HS 在這邊就可以犧牲壓縮率來換效能...

另外找了一下資料,發現有 lowzip 這個東西,走 ZIP 格式,記憶體用量也不高,不過軟體本身還掛 alpha:

Current x64 code footprint (for lowzip.c, excluding the test program) is about 3.2kB and RAM footprint is about 1.1kB.

如果之後打算要透過 LPWAN 之類的網路傳東西的話好像有可能會用到,先寫下來...

cURL 支援 Zstandard

在「curl 7.72.0 – more compression」這邊看到新版的 cURL 要支援 Zstandard 了,查了一下發現 Zstandard 有對應的 RFC,在 RFC 8478:「Zstandard Compression and the application/zstd Media Type」。

對應到 server 端的部份,看起來可以用 tokers/zstd-nginx-module 搭 (在 nginx 環境下),不然就是 application 端要自己壓縮了。

不過普及率比較高的演算法是 Google 主導的 Brotli,查了一下壓縮率大概在同一個等級。

Facebook 沒有自家瀏覽器,推這些東西比較辛苦一點,但這次 cURL 決定支援 Zstandard 算是一個開始,讓開發者多了一個選擇可以用...

補上 nginx 對 favicon 的壓縮...

從「Compressed favicons are 70% smaller but 75% of them are served uncompressed」這邊看到的,他們發現大約有 73.5% 的網站沒有壓縮 favicon.ico 檔:

The HTTP Archive dataset of favicons from 4 million websites crawled from desktop devices on May 2019 shows that 73,5 % of all favicons are offered without any compression with an average file size of 10,5 kiB, 21,5 % are offered with Gzip compression at an average file size of 4 kiB, and 5 % offer Brotli compression at an average file size of 3 kiB.

我自己的也沒加... 補上 gzip 相關的設定後,favicon.ico 的傳輸量從 4.2KB 降到 1.2KB。

我是使用 nginx,在 Ubuntu 上 nginx 的 nginx.conf 內 gzip 預設已經有開,所以只要增加一些設定讓他知道要處理 ico 檔案就可以了。

方法是在 /etc/nginx/conf.d/gzip.conf 裡面放:

gzip_comp_level 9;
gzip_types image/vnd.microsoft.icon image/x-icon;
gzip_vary on;

跟文章裡面提到的多了兩個設定,一個是 gzip_comp_level 改成 9 (預設是 1),另外有 gzip 時應該要在 Vary 表示,避免 cache 出錯。

S3 Select 宣佈支援 Parquet 與 bzip2

Amazon S3S3 Select 宣佈支援 Parquet 格式:「Amazon S3 Announces New Features for S3 Select」。

本來 S3 Select 就已經支援 CSV 與 JSON 格式,大多數的引擎也都可以直接吃,這次宣佈支援 JSON Arrays,以及 Parquet 格式:

Today, Amazon S3 Select works on objects stored in CSV and JSON format. Based on customer feedback, we’re happy to announce S3 Select support for Apache Parquet format, JSON Arrays, and BZIP2 compression for CSV and JSON objects. We are also adding support for CloudWatch Metrics for S3 Select, which lets you monitor S3 Select usage for your applications.

另外一個上面也有提到的是宣佈支援 bzip2 格式,不知道有沒有打算支援壓縮率更好的其他格式...

Cloudflare 推出在 HTTPS 下的壓縮機制

在 TLS (HTTPS) 環境下基本上都不能開壓縮,主要是為了避免 secret token 會因為 dictionary 的可預測性而被取出,像是 CRIMEBREACHTIMEHEIST (沒完結過...),而因為全面關閉壓縮,對於效能的影響很大。

Cloudflare 就試著去找方法,是否可以維持壓縮,但又不會洩漏 secret token 的方式,於是就有了這篇:「A Solution to Compression Oracles on the Web」。

重點在於 Our Solution 這段的開頭:

We decided to use selective compression, compressing only non-secret parts of a page, in order to stop the extraction of secret information from a page.

透過 regex 判斷那些東西屬於 secret token,然後對這些資料例外處理不要壓縮,而其他的部份就可以維持壓縮。這樣傳輸量仍然可以大幅下降,但不透漏 secret token。然後因為這個想法其實很特別,沒有被實證過,所以成立了 Challenge Site 讓大家打:

We have set up the challenge website compression.website with protection, and a clone of the site compression.website/unsafe without it. The page is a simple form with a per-client CSRF designed to emulate common CSRF protection. Using the example attack presented with the library we have shown that we are able to extract the CSRF from the size of request responses in the unprotected variant but we have not been able to extract it on the protected site. We welcome attempts to extract the CSRF without access to the unencrypted response.

這個方向如果可行的話,應該會有人發展一些標準讓 compression algorithm 不用猜哪些是 secret token,這樣一來就更能確保因為漏判而造成的 leaking...

Netflix 在 Time Series Data Storage 上的努力...

在「Scaling Time Series Data Storage — Part I」這篇看到 Netflix 在 Time Series Data Storage 上所做的努力...

因為應用在寫多讀少的場景,所以選擇使用 Cassandra,遇到瓶頸後把常寫入的與不太會改變的拆開儲存,並且用不同方式最佳化。包括了 cache 與 compression 都拿出來用了...

不知道他們內部有沒有評估 ScyllaDB 的想法...

基於 RNN 的無損壓縮

Hacker News 上看到「DeepZip: Lossless Compression using Recurrent Networks」這篇論文,利用 RNN 幫助壓縮技術壓的更小,而程式碼在 GitHubkedartatwawadi/NN_compression 上有公開讓大家可以測試。

裡面有個比較特別的是,Lagged Fibonacci PRNG 產生出來的資料居然有很好的壓縮率,這在傳統的壓縮方式應該都是幾乎沒有壓縮率...

整體的壓縮率都還不錯,不過比較的對象只有 gzip,沒有拿比較先進的壓縮軟體進行比較) 像是 xz 之類的),看數字猜測在一般的情況下應該不會贏太多,不過光是 PRNG 那部份,這篇論文等於是給了一個不同的方向讓大家玩...

Amazon API Gateway 支援壓縮了...

Amazon API Gateway 支援壓縮了:「Amazon API Gateway Supports Content Encoding for API Responses」。

You can now enable content encoding support for API Responses in Amazon API Gateway. Content encoding allows API clients to request content to be compressed before being sent back in the response to an API request. This reduces the amount of data that is sent from API Gateway to API clients and decreases the time it takes to transfer the data. You can enable content encoding in the API definition. You can also set the minimum response size that triggers compression. By default, APIs do not have content encoding support enabled.

打開後傳回的資料就會自動壓縮了,然後還可以設定觸發的 response size... 依照文件 (Content Codings Supported by API Gateway),目前支援的壓縮格式應該是最常見的 gzipdeflate

這功能好像是一開始有 API Gateway 就一直被提出來的 feature request...