Skip to content

Commit

Permalink
PR #611: Bzip input stream simple vectorization
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
konrad-kruczynski authored May 4, 2021
1 parent 5eea92a commit 1b9fcfc
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System;
using System.IO;
using BenchmarkDotNet.Attributes;

namespace ICSharpCode.SharpZipLib.Benchmark.BZip2
{
[Config(typeof(MultipleRuntimes))]
public class BZip2InputStream
{
private byte[] compressedData;

public BZip2InputStream()
{
var outputMemoryStream = new MemoryStream();
using (var outputStream = new SharpZipLib.BZip2.BZip2OutputStream(outputMemoryStream))
{
var random = new Random(1234);
var inputData = new byte[1024 * 1024 * 30];
random.NextBytes(inputData);
var inputMemoryStream = new MemoryStream(inputData);
inputMemoryStream.CopyTo(outputStream);
}

compressedData = outputMemoryStream.ToArray();
}

[Benchmark]
public void DecompressData()
{
var memoryStream = new MemoryStream(compressedData);
using (var inputStream = new SharpZipLib.BZip2.BZip2InputStream(memoryStream))
{
inputStream.CopyTo(Stream.Null);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFrameworks>netcoreapp2.1;net461</TargetFrameworks>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net461</TargetFrameworks>
</PropertyGroup>

<ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion benchmark/ICSharpCode.SharpZipLib.Benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public MultipleRuntimes()
{
AddJob(Job.Default.WithToolchain(CsProjClassicNetToolchain.Net461).AsBaseline()); // NET 4.6.1
AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp21)); // .NET Core 2.1
//Add(Job.Default.With(CsProjCoreToolchain.NetCoreApp30)); // .NET Core 3.0
AddJob(Job.Default.WithToolchain(CsProjCoreToolchain.NetCoreApp31)); // .NET Core 3.1
}
}

Expand Down
27 changes: 24 additions & 3 deletions src/ICSharpCode.SharpZipLib/BZip2/BZip2InputStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,11 @@ public class BZip2InputStream : Stream
private const int NO_RAND_PART_B_STATE = 6;
private const int NO_RAND_PART_C_STATE = 7;

#endregion Constants
#if NETSTANDARD2_1
private static readonly int VectorSize = System.Numerics.Vector<byte>.Count;
#endif

#endregion Constants

#region Instance Fields

Expand Down Expand Up @@ -711,10 +715,27 @@ cache misses.
unzftab[seqToUnseq[tmp]]++;
ll8[last] = seqToUnseq[tmp];

for (int j = nextSym - 1; j > 0; --j)
var j = nextSym - 1;

#if !NETSTANDARD2_0 && !NETFRAMEWORK
// This is vectorized memory move. Going from the back, we're taking chunks of array
// and write them at the new location shifted by one. Since chunks are VectorSize long,
// at the end we have to move "tail" (or head actually) of the array using a plain loop.
// If System.Numerics.Vector API is not available, the plain loop is used to do the whole copying.

while(j >= VectorSize)
{
yy[j] = yy[j - 1];
var arrayPart = new System.Numerics.Vector<byte>(yy, j - VectorSize);
arrayPart.CopyTo(yy, j - VectorSize + 1);
j -= VectorSize;
}
#endif

while(j > 0)
{
yy[j] = yy[--j];
}

yy[0] = tmp;

if (groupPos == 0)
Expand Down

0 comments on commit 1b9fcfc

Please sign in to comment.