Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
4f0d92f
Added: Basic (Unrealistic) Benchmark for Encoding/Decoding
Sewer56 Oct 2, 2021
81d034b
Clean up: Some top level code & unused code.
Sewer56 Oct 1, 2021
77f4e2a
Added: Span Returns for IByteBuffer, Copy whole Source Ahead of Time
Sewer56 Oct 1, 2021
6bca687
Added: Ignores for Nullable Checks
Sewer56 Oct 1, 2021
b08a2c5
Added: Support for ByteBuffer source; use int length.
Sewer56 Oct 1, 2021
a137708
Added: SkipLocalsInit for .NET 5 Hot Path Methods
Sewer56 Oct 1, 2021
8359201
Added: Cap Encoder Buffer size at Target
Sewer56 Oct 1, 2021
5ab9ff4
Misc Space removal in VcEncoder
Sewer56 Oct 1, 2021
242a099
Added: GC.AllocateUninitializedArray for non-zeroing array alloc.
Sewer56 Oct 1, 2021
6dd4775
Added: Optimized Vector Fill & Optimized Bounds Checks
Sewer56 Oct 2, 2021
511a0bf
Improve ByteStreamReader.ReadBytes
Sewer56 Oct 2, 2021
3688aeb
Cleanup: VCDecoder APIs
Sewer56 Oct 2, 2021
cbde3ae
Optimized: Code Tables
Sewer56 Oct 2, 2021
eb1674e
Optimize: ByteBuffer AsSpan()
Sewer56 Oct 2, 2021
e704673
Optimize: ByteBuffer PeekBytes()
Sewer56 Oct 2, 2021
a46c6c2
Optimize: ByteStreamReader ReadBytesAsSpan
Sewer56 Oct 2, 2021
faeae16
Revert: Share VcDecoder with Async Path
Sewer56 Oct 2, 2021
7b54323
Removed: Redundant ByteStreamReader Check on Pos Set
Sewer56 Oct 2, 2021
18ef7d0
Added: Devirtualization to VarIntBE
Sewer56 Oct 2, 2021
8bbaf04
Change AddressCache.FirstNear to Constant
Sewer56 Oct 2, 2021
c6414b0
ByteBuffer: Added Dispose on Finalizer if Needed
Sewer56 Oct 2, 2021
5c4c59d
Added: AsSpan where AsMemory was used by accident
Sewer56 Oct 2, 2021
9340956
Changed: Ensure Chunker is Disposed
Sewer56 Oct 2, 2021
9df4547
Added: Unsafe Tables in BlockHash so other frameworks can benefit perf
Sewer56 Oct 2, 2021
38d041f
Changed: Devirtualize VcDecoder
Sewer56 Oct 2, 2021
e0188b4
Add: Decoder Caching Support & Optimized Calls
Sewer56 Oct 2, 2021
49d48d0
Changed: Dispose VcDecoderEx only if owns Components
Sewer56 Oct 2, 2021
4363aac
Fixed: Don't dispose objects not created by parent.
Sewer56 Oct 2, 2021
845a1e4
Feature: Use Array Rental for Faster Repeat Decode
Sewer56 Oct 3, 2021
7dd621d
For the sake of my sanity with git. Generate the docs in proper place.
Sewer56 Oct 2, 2021
e2d86d2
Fixed: Overflow when numValues * sizeof(long) > max int32
Sewer56 Oct 2, 2021
bc9ec6a
Fixed: 4GB+ Allocations
Sewer56 Oct 3, 2021
24d6ef2
Optimise: Decoder Memory & MemoryStream Allocations
Sewer56 Oct 3, 2021
fc0cb90
Remove Redundant Reset call for AddressCache
Sewer56 Oct 3, 2021
c7acc65
InstructionMap isn't mutable and should be cached.
Sewer56 Oct 3, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/VCDiff.Benchmark/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using BenchmarkDotNet.Running;

namespace VCDiff.Benchmark
{
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<RandomDataDecode>();
BenchmarkRunner.Run<RandomDataEncode>();
}
}
}
85 changes: 85 additions & 0 deletions src/VCDiff.Benchmark/RandomDataDecode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using VCDiff.Decoders;
using VCDiff.Encoders;

namespace VCDiff.Benchmark
{
[MemoryDiagnoser()]
[SimpleJob(1, 3, 8)]
public class RandomDataDecode
{
[Params(//1 * 1024 * 256, // 0.25MiB
//1 * 1024 * 1024, // 2 MiB
16 * 1024 * 1024 // 16 MiB
)]
public int Bytes { get; set; }

[Params(32)] // AVX Only
//[Params(16, 32)] // AVX vs SSE
public int BlockSize { get; set; }

private const int RepeatCount = 128;
private byte[] _data;
private Stream _patchSlightModified;
private Stream _patchHeavyModified;

private Stream _sourceStream;

[GlobalSetup]
public void GlobalSetup()
{
_data = RandomDataGenerator.GetRandomBytes(Bytes);
RandomDataEncode.MakeRandomData(_data, out var dataSlightModified, out var dataHeavyModified);

// Make Source Stream
_sourceStream = new MemoryStream(_data);

// Make Slightly Mod Patch
CreatePatch(dataSlightModified, ref _patchSlightModified);
CreatePatch(dataHeavyModified, ref _patchHeavyModified);
}

private void CreatePatch(byte[] targetData, ref Stream receiver)
{
_sourceStream.Seek(0, SeekOrigin.Begin);
receiver = new MemoryStream(_data.Length);
using var targetStream = new MemoryStream(targetData);
using var encoder = new VcEncoder(_sourceStream, targetStream, receiver, 1, BlockSize);
encoder.Encode();
}

[Benchmark]
public void DecodeSlightlyModified()
{
using var result = new MemoryStream((int)_sourceStream.Length);
for (int x = 0; x < RepeatCount; x++)
{
_sourceStream.Seek(0, SeekOrigin.Begin);
_patchSlightModified.Seek(0, SeekOrigin.Begin);
result.Position = 0;
using var decoder = new VcDecoder(_sourceStream, _patchSlightModified, result, int.MaxValue);
decoder.Decode(out long written);
}
}

[Benchmark]
public void DecodeHeavilyModified()
{
using var result = new MemoryStream((int)_sourceStream.Length);
for (int x = 0; x < RepeatCount; x++)
{
_sourceStream.Seek(0, SeekOrigin.Begin);
_patchHeavyModified.Seek(0, SeekOrigin.Begin);
result.Position = 0;
using var decoder = new VcDecoder(_sourceStream, _patchHeavyModified, result, int.MaxValue);
decoder.Decode(out long written);
}
}
}
}
77 changes: 77 additions & 0 deletions src/VCDiff.Benchmark/RandomDataEncode.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
using System;
using System.IO;
using BenchmarkDotNet.Attributes;
using VCDiff.Encoders;

namespace VCDiff.Benchmark
{
[MemoryDiagnoser()]
[SimpleJob(1, 3, 8)]
public class RandomDataEncode
{
[Params(//1 * 1024 * 256, // 0.25MiB
//1 * 1024 * 1024, // 2 MiB
16 * 1024 * 1024 // 16 MiB
)]
public int Bytes { get; set; }

[Params(32)] // AVX Only
//[Params(16, 32)] // AVX vs SSE
public int BlockSize { get; set; }

private byte[] _data;
private byte[] _dataSlightModified;
private byte[] _dataHeavyModified;

private Stream _sourceStream;

[GlobalSetup]
public void GlobalSetup()
{
_data = RandomDataGenerator.GetRandomBytes(Bytes);
MakeRandomData(_data, out _dataSlightModified, out _dataHeavyModified);
_sourceStream = new MemoryStream(_data);
}

[IterationSetup]
public void IterationSetup() => _sourceStream.Seek(0, SeekOrigin.Begin);

[Benchmark]
public void EncodeSlightlyModified()
{
using var targetStream = new MemoryStream(_dataSlightModified);
using var patchStream = new MemoryStream(_data.Length);

using var encoder = new VcEncoder(_sourceStream, targetStream, patchStream, 1, BlockSize);
encoder.Encode();
}

[Benchmark]
public void EncodeHeavilyModified()
{
using var targetStream = new MemoryStream(_dataHeavyModified);
using var patchStream = new MemoryStream(_data.Length);

using var encoder = new VcEncoder(_sourceStream, targetStream, patchStream, 1, BlockSize);
encoder.Encode();
}


// Utility Methods
public static void MakeRandomData(byte[] data, out byte[] dataSlightModified, out byte[] dataHeavyModified)
{
dataSlightModified = (byte[])data.Clone();
dataHeavyModified = (byte[])data.Clone();

var random = new Random(data.Length);
for (int x = 0; x < dataHeavyModified.Length; x++)
{
var next = random.Next(0, 1000);
if (next >= 250) // 3 / 4 chance.
dataHeavyModified[x] += (byte)next;
if (next >= 995) // 1 / 200 chance.
dataSlightModified[x] += (byte)next;
}
}
}
}
20 changes: 20 additions & 0 deletions src/VCDiff.Benchmark/RandomDataGenerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System;

namespace VCDiff.Benchmark
{
/// <summary>
/// Generates random data.
/// </summary>
public static class RandomDataGenerator
{
public static byte[] GetRandomBytes(int size)
{
var data = new byte[size];
var random = new Random(size);
for (int x = 0; x < data.Length; x++)
data[x] = (byte)random.Next();

return data;
}
}
}
16 changes: 16 additions & 0 deletions src/VCDiff.Benchmark/VCDiff.Benchmark.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\VCDiff\VCDiff.csproj" />
</ItemGroup>

</Project>
10 changes: 3 additions & 7 deletions src/VCDiff.Tests/FileDiffTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -522,18 +522,14 @@ public void MaxFileSize_Test()
long bytesWritten = 0;

using VcDecoder decoder = new VcDecoder(srcStream, deltaStream, outputStream, -1);
ArgumentException ex = Assert.Throws<ArgumentException>(() => decoder.Decode(out bytesWritten));
Assert.Matches(@"maxWindowSize must be a positive value", ex.Message);
Assert.Throws<ArgumentException>(() => decoder.Decode(out bytesWritten));

srcStream.Position = 0;
targetStream.Position = 0;
deltaStream.Position = 0;

using VcDecoder decoder1 = new VcDecoder(srcStream, deltaStream, outputStream, 2);
InvalidOperationException ex1 = Assert.Throws<InvalidOperationException>(() => decoder1.Decode(out bytesWritten));
Assert.Matches(@"Length of target window \(\d*\) exceeds limit of 2 bytes", ex1.Message);


using VcDecoder decoder1 = new VcDecoder(srcStream, deltaStream, outputStream, 2);
Assert.Throws<InvalidOperationException>(() => decoder1.Decode(out bytesWritten));
}
}
}
8 changes: 7 additions & 1 deletion src/VCDiff.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ VisualStudioVersion = 16.0.29721.120
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VCDiff", "VCDiff\VCDiff.csproj", "{4D676F4E-E66D-4A41-861F-600F0FFCD052}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCDiff.Tests", "VCDiff.Tests\VCDiff.Tests.csproj", "{724A8CFC-F566-47BB-ABE7-2A7DF5EC4E66}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VCDiff.Tests", "VCDiff.Tests\VCDiff.Tests.csproj", "{724A8CFC-F566-47BB-ABE7-2A7DF5EC4E66}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VCDiff.Benchmark", "VCDiff.Benchmark\VCDiff.Benchmark.csproj", "{29FF95D4-B9BF-480B-B0F1-E5A0BAEAAA82}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -21,6 +23,10 @@ Global
{724A8CFC-F566-47BB-ABE7-2A7DF5EC4E66}.Debug|Any CPU.Build.0 = Debug|Any CPU
{724A8CFC-F566-47BB-ABE7-2A7DF5EC4E66}.Release|Any CPU.ActiveCfg = Release|Any CPU
{724A8CFC-F566-47BB-ABE7-2A7DF5EC4E66}.Release|Any CPU.Build.0 = Release|Any CPU
{29FF95D4-B9BF-480B-B0F1-E5A0BAEAAA82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{29FF95D4-B9BF-480B-B0F1-E5A0BAEAAA82}.Debug|Any CPU.Build.0 = Debug|Any CPU
{29FF95D4-B9BF-480B-B0F1-E5A0BAEAAA82}.Release|Any CPU.ActiveCfg = Release|Any CPU
{29FF95D4-B9BF-480B-B0F1-E5A0BAEAAA82}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Loading