Сжатие Zstandard в .NET 11
В .NET уже некоторое время существуют DeflateStream, GZipStream, ZLibStream и BrotliStream. В .NET 11 к ним присоединяется новый: ZstandardStream.
Zstandard (или Zstd) — это алгоритм сжатия от Facebook. Разработан для обеспечения коэффициента сжатия, сравнимого с алгоритмом DEFLATE, но более быстрого, особенно для декомпрессии. Он настраивается с уровнями сжатия от -7 (самый быстрый) до 22 (самый медленный по скорости сжатия, но с наилучшим коэффициентом сжатия). Zstd используется в ядре Linux, дампах памяти FreeBSD, AWS Redshift, менеджерах пакетов Fedora и ArchLinux, а также архивах игр Nintendo Switch.
Новый API
Дизайн соответствует существующему шаблону Brotli*, поэтому, если вы использовали BrotliStream или BrotliEncoder, он покажется вам знакомым.
В System.IO.Compression 4 основных новых типа:
- ZstandardStream — обёртка потока,
- ZstandardEncoder/ZstandardDecoder — кодировщик/декодировщик,
- ZstandardDictionary — для эффективного сжатия множества маленьких файлов,
- ZstandardCompressionOptions — настройки: качество, размер окна, контрольная сумма и т.п.
Простейший пример применения:
// сжатие
using var output = new MemoryStream();
using (var zstd =
new ZstandardStream(output, CompressionMode.Compress))
{
await inputStream.CopyToAsync(zstd);
}
// декомпрессия
using var zstd = new
ZstandardStream(compressedStream, CompressionMode.Decompress);
await zstd.CopyToAsync(outputStream);
Если не требуется потоковая обработка, есть API проще:
byte[] src = File.ReadAllBytes("data.bin");
// сжатие
int maxLen = ZstandardEncoder
.GetMaxCompressedLength(src.Length);
var compressed = new byte[maxLen];
ZstandardEncoder.TryCompress(src, compressed, out int bytesWritten);
// декомпрессия
int decompressedSize = ZstandardDecoder.GetMaxDecompressedLength(compressed.AsSpan(0, bytesWritten));
var decompressed = new byte[decompressedSize];
ZstandardDecoder.TryDecompress(compressed.AsSpan(0, bytesWritten), decompressed, out int bytesRead);Уровни качества
Zstd имеет диапазон качества от ZSTD_minCLevel() (который может быть отрицательным для сверхбыстрых режимов) до 22, по умолчанию 3. CompressionLevel.Fastest - минимальное значение, CompressionLevel.SmallestSize — 22.
var options = new ZstandardCompressionOptions
{
Quality = 6
};
using var zstd = new ZstandardStream(output, options);
Использование в ASP.NET Core
// Program.cs
builder.Services.AddResponseCompression(x =>
{
x.EnableForHttps = true;
x.Providers.Add<ZstandardCompressionProvider>();
});
ZstandardCompressionProvider автоматически подключает заголовок согласования содержимого
encoding: zstd. Распаковка запроса также осуществляется простым способом через IDecompressionProvider.Сжатие по словарю
При сжатии большого количества небольших, похожих данных (ответы JSON API, сериализованные события, блоки конфигурации) общий словарь может улучшить коэффициент сжатия.
// обучаем словарь на примерах
byte[] allSamples = …; // примеры всех сжимаемых объектов
int[] lengths = …; // длина каждого примера
using ZstandardDictionary dict = ZstandardDictionary.TrainFromSamples(allSamples, lengths, maxDictionarySize: 100_000);
// Сжатие по словарю — обе стороны должны использовать один словарь
using var encoder = new ZstandardEncoder(dict);
encoder.Compress(payload, compressed, out int consumed, out int written, isFinalBlock: true);
Храните словарь в месте, доступном как производителю, так и потребителю. Рекомендуемый размер — до 100 КБ, обучение проводится на репрезентативных данных, размер которых примерно в 100 раз превышает размер сжимаемых данных.
Источник: https://steven-giesel.com/blogPost/6066abb6-640a-4225-ac33-3f4d5a1a1d16/zstandard-compression-in-net-11