Skip to content

Commit

Permalink
Handle null chunk type using enum value (#83)
Browse files Browse the repository at this point in the history
Motivation
----------
Trying to narrow down perf loss in .NET 8 compared to .NET 6 specific to
stream decompression.

Modifications
-------------
Rather than using a `Nullable<ChunkType>` to track when the chunk type
is unknown, add an enum value that represents null.

Results
-------
BenchmarkDotNet v0.13.10, Windows 11
(10.0.22621.2861/22H2/2022Update/SunValley2) 12th Gen Intel Core
i7-1270P, 1 CPU, 16 logical and 12 physical cores .NET SDK 8.0.100
  [Host]     : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
Job-AODULB : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT
VectorSize=256
Job-AZPVRO : .NET Framework 4.8.1 (4.8.9181.0), X64 RyuJIT
VectorSize=256
  Job-FTJSLO : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
  Job-XMQQAK : .NET 6.0.25 (6.0.2523.51912), X64 RyuJIT AVX2
  Job-IPTUCK : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
  Job-YAGJLP : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
  Job-DJZUQL : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2
  Job-FFPERJ : .NET 8.0.0 (8.0.23.53103), X64 RyuJIT AVX2

| Method | Runtime | BuildConfiguration | PGO | ReadSize | Mean | Error
| StdDev | Ratio | Rank |
|----------- |------------------- |------------------- |---- |---------
|---------:|--------:|--------:|------:|-----:|
| Decompress | .NET Framework 4.8 | Previous | N | 16384 | 340.4 us |
2.56 us | 2.39 us | 1.00 | 2 |
| Decompress | .NET Framework 4.8 | Default | N | 16384 | 332.2 us |
2.64 us | 2.34 us | 0.98 | 1 |
| | | | | | | | | | |
| Decompress | .NET 6.0 | Previous | N | 16384 | 167.5 us | 1.11 us |
1.04 us | 1.00 | 1 |
| Decompress | .NET 6.0 | Default | N | 16384 | 167.5 us | 2.44 us |
2.16 us | 1.00 | 1 |
| | | | | | | | | | |
| Decompress | .NET 8.0 | Previous | N | 16384 | 200.7 us | 1.19 us |
1.06 us | 1.00 | 2 |
| Decompress | .NET 8.0 | Default | N | 16384 | 191.7 us | 1.47 us |
1.30 us | 0.96 | 1 |
| | | | | | | | | | |
| Decompress | .NET 8.0 | Previous | Y | 16384 | 199.1 us | 0.94 us |
0.88 us | 1.00 | 2 |
| Decompress | .NET 8.0 | Default | Y | 16384 | 189.9 us | 0.91 us |
0.85 us | 0.95 | 1 |

Note: Benchmarks include other improvements since 1.1.3
  • Loading branch information
brantburnett authored Jan 6, 2024
1 parent 777936b commit 9d07b42
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 6 deletions.
6 changes: 5 additions & 1 deletion Snappier/Internal/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,11 @@ public enum ChunkType : byte
UncompressedData = 0x01,
SkippableChunk = 0x80, // If this bit is set, we can safely skip the chunk if unknown
Padding = 0xfe,
StreamIdentifier = 0xff
StreamIdentifier = 0xff,

// This is not part of the spec, but having this extra value representing null avoids
// the cost of wrapping in a Nullable<T>
Null = 0xfd,
}

public const byte Literal = 0b00;
Expand Down
10 changes: 5 additions & 5 deletions Snappier/Internal/SnappyStreamDecompressor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal sealed class SnappyStreamDecompressor : IDisposable

private readonly byte[] _scratch = new byte[ScratchBufferSize];
private int _scratchLength;
private Constants.ChunkType? _chunkType;
private Constants.ChunkType _chunkType = Constants.ChunkType.Null;
private int _chunkSize;
private int _chunkBytesProcessed;
private uint _expectedChunkCrc;
Expand All @@ -40,7 +40,7 @@ public int Decompress(Span<byte> buffer)
// ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
switch (_chunkType)
{
case null:
case Constants.ChunkType.Null:
// Not in a chunk, read the chunk type and size

uint rawChunkHeader = ReadChunkHeader(ref input);
Expand Down Expand Up @@ -106,7 +106,7 @@ public int Decompress(Span<byte> buffer)
if (_decompressor.EndOfFile)
{
// Completed reading the chunk
_chunkType = null;
_chunkType = Constants.ChunkType.Null;

uint crc = Crc32CAlgorithm.ApplyMask(_chunkCrc);
if (_expectedChunkCrc != crc)
Expand Down Expand Up @@ -149,7 +149,7 @@ public int Decompress(Span<byte> buffer)
if (_chunkBytesProcessed >= _chunkSize)
{
// Completed reading the chunk
_chunkType = null;
_chunkType = Constants.ChunkType.Null;

uint crc = Crc32CAlgorithm.ApplyMask(_chunkCrc);
if (_expectedChunkCrc != crc)
Expand All @@ -176,7 +176,7 @@ public int Decompress(Span<byte> buffer)
if (_chunkBytesProcessed >= _chunkSize)
{
// Completed reading the chunk
_chunkType = null;
_chunkType = Constants.ChunkType.Null;
}

break;
Expand Down

0 comments on commit 9d07b42

Please sign in to comment.