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..2f4ca8132aa --- /dev/null +++ b/src/benchmarks/micro/libraries/System.IO.Compression/Zstandard.cs @@ -0,0 +1,76 @@ + +// 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; + +#if NET11_0_OR_GREATER + +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; + } +} + +#endif \ No newline at end of file