Skip to content

Commit 96af092

Browse files
committed
Compression benchmarks
1 parent 398d094 commit 96af092

File tree

6 files changed

+199
-1
lines changed

6 files changed

+199
-1
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
bin/
22
obj/
3-
.vs/
3+
.vs/
4+
BenchmarkDotNet.Artifacts/

src/ZLibDotNet.sln

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZLibDotNet", "ZLibDotNet\ZL
77
EndProject
88
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ZLibDotNet.UnitTests", "..\tests\ZLibDotNet.UnitTests\ZLibDotNet.UnitTests.csproj", "{A7B277F4-1311-4CAA-B234-D32E6235780C}"
99
EndProject
10+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZLibDotNet.Benchmarks", "..\tests\ZLibDotNet.Benchmarks\ZLibDotNet.Benchmarks.csproj", "{3EAA576D-1779-4511-B279-1ABCAB606FE5}"
11+
EndProject
1012
Global
1113
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1214
Debug|Any CPU = Debug|Any CPU
@@ -21,6 +23,10 @@ Global
2123
{A7B277F4-1311-4CAA-B234-D32E6235780C}.Debug|Any CPU.Build.0 = Debug|Any CPU
2224
{A7B277F4-1311-4CAA-B234-D32E6235780C}.Release|Any CPU.ActiveCfg = Release|Any CPU
2325
{A7B277F4-1311-4CAA-B234-D32E6235780C}.Release|Any CPU.Build.0 = Release|Any CPU
26+
{3EAA576D-1779-4511-B279-1ABCAB606FE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27+
{3EAA576D-1779-4511-B279-1ABCAB606FE5}.Debug|Any CPU.Build.0 = Debug|Any CPU
28+
{3EAA576D-1779-4511-B279-1ABCAB606FE5}.Release|Any CPU.ActiveCfg = Release|Any CPU
29+
{3EAA576D-1779-4511-B279-1ABCAB606FE5}.Release|Any CPU.Build.0 = Release|Any CPU
2430
EndGlobalSection
2531
GlobalSection(SolutionProperties) = preSolution
2632
HideSolutionNode = FALSE
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
using System.Buffers;
2+
using System.IO.Compression;
3+
using System.Text;
4+
using BenchmarkDotNet.Attributes;
5+
using ICSharpCode.SharpZipLib.Zip.Compression;
6+
using Ionic.Zlib;
7+
using Elskom.Generic.Libs;
8+
using CompressionLevel = System.IO.Compression.CompressionLevel;
9+
10+
namespace ZLibDotNet.Benchmarks;
11+
12+
[MemoryDiagnoser]
13+
[MValueColumn]
14+
public class CompressionBenchmarks
15+
{
16+
private const int OutputBufferSize = 1000;
17+
private static readonly ZLib s_zlib = new();
18+
19+
public IEnumerable<byte[]> Input { get; } = new[]
20+
{
21+
Encoding.ASCII.GetBytes("hello, hello!"),
22+
Encoding.ASCII.GetBytes("0|1|4|14 15 695 12 13 524 36 38 71 60 61 72 3 435 436 30 119"),
23+
Encoding.ASCII.GetBytes("0|1|128|99 3 4 100 432 102 103 104 422 105 106 107 108 109 110 111 112 113 98 97 114 40 29 30 66 21 22 23 24 54 55 179 180 181 182 187 202 203 382 383"),
24+
Encoding.ASCII.GetBytes("0|0|16|3 4 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 54 55 499 64 65 66 90 91 92 98 104 422 110 615 119 168 169 170 171 616 617 618 619 443 172 188 204 205 206 207 208 209 210 211 212 213 214 243 244 245 246 247 248 251 252 253 254 255 256 257 258 259 260 290 291 292 293 294 295 296 319 297 298 299 300 304 305 306 307 308 309 310 313 314 315 316 317 318 320 322 323 324 332 336 337 338 125 340 341 342 346 347 348 438 349 350 351 352 353 360 361 362 363 365 366 375 384 410 411 412 423 424 425 426 427 428 429 433 434 437 441 622 623 689 690 691 693 694 710 711 712 732 733"),
25+
Encoding.ASCII.GetBytes("AliceBlue AntiqueWhite Aqua Aquamarine Azure Beige Bisque Black BlanchedAlmond Blue BlueViolet Brown BurlyWood CadetBlue Chartreuse Chocolate Coral CornflowerBlue Cornsilk Crimson Cyan DarkBlue DarkCyan DarkGoldenrod DarkGray DarkGreen DarkKhaki DarkMagenta DarkOliveGreen DarkOrange DarkOrchid DarkRed DarkSalmon DarkSeaGreen DarkSlateBlue DarkSlateGray DarkTurquoise DarkViolet DeepPink DeepSkyBlue DimGray DodgerBlue Firebrick FloralWhite ForestGreen Fuchsia Gainsboro GhostWhite Gold Goldenrod Gray Green GreenYellow Honeydew HotPink IndianRed Indigo Ivory Khaki Lavender LavenderBlush LawnGreen LemonChiffon LightBlue LightCoral LightCyan LightGoldenrodYellow LightGray LightGreen LightPink LightSalmon LightSeaGreen LightSkyBlue LightSlateGray LightSteelBlue LightYellow Lime LimeGreen Linen Magenta Maroon MediumAquamarine MediumBlue MediumOrchid MediumPurple MediumSeaGreen MediumSlateBlue MediumSpringGreen MediumTurquoise MediumVioletRed MidnightBlue MintCream MistyRose Moccasin NavajoWhite Navy OldLace Olive OliveDrab Orange OrangeRed Orchid PaleGoldenrod PaleGreen PaleTurquoise PaleVioletRed PapayaWhip PeachPuff Peru Pink Plum PowderBlue Purple Red RosyBrown RoyalBlue SaddleBrown Salmon SandyBrown SeaGreen SeaShell Sienna Silver SkyBlue SlateBlue SlateGray Snow SpringGreen SteelBlue Tan Teal Thistle Tomato Transparent Turquoise Violet Wheat White WhiteSmoke Yellow YellowGreen")
26+
};
27+
28+
[Params(1, 6, 9)]
29+
public int Level { get; set; }
30+
31+
#pragma warning disable CA1062
32+
[Benchmark(Baseline = true)]
33+
[ArgumentsSource(nameof(Input))]
34+
public void ZLibDotNet(byte[] input)
35+
{
36+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
37+
38+
ZStream zStream = new()
39+
{
40+
Input = input,
41+
Output = outputBuffer
42+
};
43+
_ = s_zlib.DeflateInit(zStream, Level);
44+
_ = s_zlib.Deflate(zStream, Z_FINISH);
45+
_ = s_zlib.DeflateEnd(zStream);
46+
47+
ArrayPool<byte>.Shared.Return(outputBuffer);
48+
}
49+
50+
[Benchmark]
51+
[ArgumentsSource(nameof(Input))]
52+
public unsafe void ZLibDotNetUnsafe(byte[] input)
53+
{
54+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
55+
56+
fixed (byte* nextIn = input, nextOut = outputBuffer)
57+
{
58+
Unsafe.ZStream zStream = new()
59+
{
60+
NextIn = nextIn,
61+
AvailableIn = (uint)input.Length,
62+
NextOut = nextOut,
63+
AvailableOut = OutputBufferSize
64+
};
65+
_ = s_zlib.DeflateInit(zStream, Level);
66+
_ = s_zlib.Deflate(zStream, Z_FINISH);
67+
_ = s_zlib.DeflateEnd(zStream);
68+
}
69+
70+
ArrayPool<byte>.Shared.Return(outputBuffer);
71+
}
72+
73+
[Benchmark]
74+
[ArgumentsSource(nameof(Input))]
75+
public void DotNet6(byte[] input)
76+
{
77+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
78+
79+
using MemoryStream dest = new();
80+
using (ZLibStream zLibStream = new(dest, GetCompressionLevel(Level), true))
81+
zLibStream.Write(input, 0, input.Length);
82+
dest.Position = 0;
83+
_ = dest.Read(outputBuffer, 0, OutputBufferSize);
84+
85+
ArrayPool<byte>.Shared.Return(outputBuffer);
86+
87+
static CompressionLevel GetCompressionLevel(int level) => level switch
88+
{
89+
1 => CompressionLevel.Fastest,
90+
9 => CompressionLevel.SmallestSize,
91+
_ => CompressionLevel.Optimal,
92+
};
93+
}
94+
95+
[Benchmark]
96+
[ArgumentsSource(nameof(Input))]
97+
public void DotNetZip(byte[] input)
98+
{
99+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
100+
101+
ZlibCodec zlibCodec = new()
102+
{
103+
InputBuffer = input,
104+
AvailableBytesIn = input.Length,
105+
OutputBuffer = outputBuffer,
106+
AvailableBytesOut = OutputBufferSize
107+
};
108+
_ = zlibCodec.InitializeDeflate((Ionic.Zlib.CompressionLevel)Level);
109+
_ = zlibCodec.Deflate(FlushType.Finish);
110+
_ = zlibCodec.EndDeflate();
111+
112+
ArrayPool<byte>.Shared.Return(outputBuffer);
113+
}
114+
115+
[Benchmark]
116+
[ArgumentsSource(nameof(Input))]
117+
public void SharpZipLib(byte[] input)
118+
{
119+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
120+
121+
Deflater deflater = new();
122+
deflater.SetLevel(Level);
123+
deflater.SetInput(input, 0, input.Length);
124+
deflater.Finish();
125+
_ = deflater.Deflate(outputBuffer, 0, OutputBufferSize);
126+
127+
ArrayPool<byte>.Shared.Return(outputBuffer);
128+
}
129+
130+
[Benchmark]
131+
[ArgumentsSource(nameof(Input))]
132+
public void ZlibManaged(byte[] input)
133+
{
134+
byte[] outputBuffer = ArrayPool<byte>.Shared.Rent(OutputBufferSize);
135+
136+
using MemoryStream dest = new();
137+
using (ZOutputStream zOutputStream = new(dest, Level == 6 ? ZlibCompression.ZDEFAULTCOMPRESSION
138+
: (ZlibCompression)Level))
139+
{
140+
zOutputStream.Write(input, 0, input.Length);
141+
zOutputStream.Finish();
142+
dest.Position = 0;
143+
_ = dest.Read(outputBuffer, 0, OutputBufferSize);
144+
}
145+
146+
ArrayPool<byte>.Shared.Return(outputBuffer);
147+
}
148+
#pragma warning restore CA1062
149+
}
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
global using static ZLibDotNet.ZLib;
2+
using BenchmarkDotNet.Running;
3+
using System.Reflection;
4+
5+
[assembly: CLSCompliant(false)]
6+
7+
#pragma warning disable CA1812 //https://github.com/dotnet/roslyn-analyzers/issues/5628
8+
BenchmarkSwitcher.FromAssembly(Assembly.GetExecutingAssembly()).Run(args);
9+
#pragma warning restore CA1812

tests/ZLibDotNet.Benchmarks/README.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
### How to run the benchmarks?
2+
3+
- Install the [.NET 6 SDK](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)
4+
- Clone this repository: `git clone https://github.com/mgnsm/ZLibDotNet.git`
5+
- Run the [dotnet run](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-run) command: `dotnet run --project tests/ZLibDotNet.Benchmarks -c Release -f net6.0 -- -f *`
6+
7+
Please refer to [BenchmarkDotNet.org](https://benchmarkdotnet.org/index.html) to learn more about how to configure and run the benchmarks.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>net6.0</TargetFramework>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>disable</Nullable>
8+
<NoWarn>CA1822</NoWarn>
9+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
10+
<AnalysisMode>All</AnalysisMode>
11+
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
12+
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
13+
</PropertyGroup>
14+
15+
<ItemGroup>
16+
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
17+
<PackageReference Include="DotNetZip" Version="1.16.0" />
18+
<PackageReference Include="SharpZipLib" Version="1.3.3" />
19+
<PackageReference Include="zlib.managed" Version="1.1.5-preview-99682104" />
20+
</ItemGroup>
21+
22+
<ItemGroup>
23+
<ProjectReference Include="..\..\src\ZLibDotNet\ZLibDotNet.csproj" />
24+
</ItemGroup>
25+
26+
</Project>

0 commit comments

Comments
 (0)