Skip to content

Commit 1b9fcfc

Browse files
PR #611: Bzip input stream simple vectorization
* Added benchmark for BZip2 decompression. * Updated benchmarks to be run also on .NET Core 3.1. * Simple automatic vectorization of the rotation loop. * Added comment describing vectorization.
1 parent 5eea92a commit 1b9fcfc

File tree

4 files changed

+63
-5
lines changed

4 files changed

+63
-5
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System;
2+
using System.IO;
3+
using BenchmarkDotNet.Attributes;
4+
5+
namespace ICSharpCode.SharpZipLib.Benchmark.BZip2
6+
{
7+
[Config(typeof(MultipleRuntimes))]
8+
public class BZip2InputStream
9+
{
10+
private byte[] compressedData;
11+
12+
public BZip2InputStream()
13+
{
14+
var outputMemoryStream = new MemoryStream();
15+
using (var outputStream = new SharpZipLib.BZip2.BZip2OutputStream(outputMemoryStream))
16+
{
17+
var random = new Random(1234);
18+
var inputData = new byte[1024 * 1024 * 30];
19+
random.NextBytes(inputData);
20+
var inputMemoryStream = new MemoryStream(inputData);
21+
inputMemoryStream.CopyTo(outputStream);
22+
}
23+
24+
compressedData = outputMemoryStream.ToArray();
25+
}
26+
27+
[Benchmark]
28+
public void DecompressData()
29+
{
30+
var memoryStream = new MemoryStream(compressedData);
31+
using (var inputStream = new SharpZipLib.BZip2.BZip2InputStream(memoryStream))
32+
{
33+
inputStream.CopyTo(Stream.Null);
34+
}
35+
}
36+
}
37+
}

benchmark/ICSharpCode.SharpZipLib.Benchmark/ICSharpCode.SharpZipLib.Benchmark.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
5+
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
66
</PropertyGroup>
77

88
<ItemGroup>

benchmark/ICSharpCode.SharpZipLib.Benchmark/Program.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public MultipleRuntimes()
1313
{
1414
AddJob(Job.Default.WithToolchain(CsProjClassicNetToolchain.Net461).AsBaseline()); // NET 4.6.1
1515
AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp21)); // .NET Core 2.1
16-
//Add(Job.Default.With(CsProjCoreToolchain.NetCoreApp30)); // .NET Core 3.0
16+
AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp31)); // .NET Core 3.1
1717
}
1818
}
1919

src/ICSharpCode.SharpZipLib/BZip2/BZip2InputStream.cs

+24-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,11 @@ public class BZip2InputStream : Stream
1919
private const int NO_RAND_PART_B_STATE = 6;
2020
private const int NO_RAND_PART_C_STATE = 7;
2121

22-
#endregion Constants
22+
#if NETSTANDARD2_1
23+
private static readonly int VectorSize = System.Numerics.Vector<byte>.Count;
24+
#endif
25+
26+
#endregion Constants
2327

2428
#region Instance Fields
2529

@@ -711,10 +715,27 @@ cache misses.
711715
unzftab[seqToUnseq[tmp]]++;
712716
ll8[last] = seqToUnseq[tmp];
713717

714-
for (int j = nextSym - 1; j > 0; --j)
718+
var j = nextSym - 1;
719+
720+
#if !NETSTANDARD2_0 && !NETFRAMEWORK
721+
// This is vectorized memory move. Going from the back, we're taking chunks of array
722+
// and write them at the new location shifted by one. Since chunks are VectorSize long,
723+
// at the end we have to move "tail" (or head actually) of the array using a plain loop.
724+
// If System.Numerics.Vector API is not available, the plain loop is used to do the whole copying.
725+
726+
while(j >= VectorSize)
715727
{
716-
yy[j] = yy[j - 1];
728+
var arrayPart = new System.Numerics.Vector<byte>(yy, j - VectorSize);
729+
arrayPart.CopyTo(yy, j - VectorSize + 1);
730+
j -= VectorSize;
717731
}
732+
#endif
733+
734+
while(j > 0)
735+
{
736+
yy[j] = yy[--j];
737+
}
738+
718739
yy[0] = tmp;
719740

720741
if (groupPos == 0)

0 commit comments

Comments
 (0)