From a51e81e3f4cd9073db388b35146f0cbcff50c98a Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Wed, 24 Sep 2025 17:27:16 +0200 Subject: [PATCH 1/2] Add benchmarks for Zstandard --- .../System.IO.Compression/Zstandard.cs | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs diff --git a/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs b/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs new file mode 100644 index 00000000000..7118e832b4f --- /dev/null +++ b/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs @@ -0,0 +1,72 @@ + +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace System.IO.Compression +{ + [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)] + public class Zstandard : CompressionStreamPerfTestBase + { + private const int Window = 22; + + public override Stream CreateStream(Stream stream, CompressionMode mode) => new ZstandardStream(stream, mode); + public override Stream CreateStream(Stream stream, CompressionLevel level) => new ZstandardStream(stream, level); + + [Benchmark] + public Span Compress_WithState() + { + using (ZstandardEncoder encoder = new ZstandardEncoder(GetQuality(level), Window)) + { + Span output = new Span(CompressedFile.CompressedData); + ReadOnlySpan input = CompressedFile.UncompressedData; + while (!input.IsEmpty && !output.IsEmpty) + { + encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock: false); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + encoder.Compress(input, output, out int bytesConsumed2, out int written2, isFinalBlock: true); + + return output; + } + } + + [Benchmark] + public Span Decompress_WithState() // the level argument is not used here, but it describes how the data was compressed (in the benchmark id) + { + using (ZstandardDecoder decoder = new ZstandardDecoder()) + { + Span output = new Span(CompressedFile.UncompressedData); + ReadOnlySpan input = CompressedFile.CompressedData; + while (!input.IsEmpty && !output.IsEmpty) + { + decoder.Decompress(input, output, out int bytesConsumed, out int written); + input = input.Slice(bytesConsumed); + output = output.Slice(written); + } + + return output; + } + } + + [Benchmark] + [MemoryRandomization] + public bool Compress_WithoutState() + => ZstandardEncoder.TryCompress(CompressedFile.UncompressedData, CompressedFile.CompressedData, out int bytesWritten, GetQuality(level), Window); + + /// + /// The perf tests for the instant decompression aren't exactly indicative of real-world scenarios since they require you to know + /// either the exact figure or the upper bound of the uncompressed size of your given compressed data. + /// + [Benchmark] + public bool Decompress_WithoutState() // the level argument is not used here, but it describes how the data was compressed (in the benchmark id) + => ZstandardDecoder.TryDecompress(CompressedFile.CompressedData, CompressedFile.UncompressedData, out int bytesWritten); + + private static int GetQuality(CompressionLevel compressLevel) + => compressLevel == CompressionLevel.Optimal ? 11 : compressLevel == CompressionLevel.Fastest ? 1 : 0; + } +} From 5674f8f892451db56a1ca6c1b9097dc20215fbf3 Mon Sep 17 00:00:00 2001 From: Radek Zikmund Date: Thu, 25 Sep 2025 09:18:36 +0200 Subject: [PATCH 2/2] Wrap with NET11_0_OR_GREATER --- .../micro/libraries/System.IO.Compression/Zstandard.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs b/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs index 7118e832b4f..2f4ca8132aa 100644 --- a/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs +++ b/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs @@ -6,6 +6,8 @@ using BenchmarkDotNet.Attributes; using MicroBenchmarks; +#if NET11_0_OR_GREATER + namespace System.IO.Compression { [BenchmarkCategory(Categories.Libraries, Categories.NoWASM)] @@ -70,3 +72,5 @@ private static int GetQuality(CompressionLevel compressLevel) => compressLevel == CompressionLevel.Optimal ? 11 : compressLevel == CompressionLevel.Fastest ? 1 : 0; } } + +#endif \ No newline at end of file