Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,63 +10,46 @@ namespace System.IO.Compression
{
public abstract class CompressionStreamPerfTestBase : CompressionStreamTestBase
{
public static IEnumerable<object[]> CanterburyCorpus_WithCompressionLevel()
public static IEnumerable<object[]> UncompressedTestFiles_WithCompressionLevel()
{
foreach (CompressionLevel compressionLevel in Enum.GetValues(typeof(CompressionLevel)))
{
foreach (object[] canterburyWithoutLevel in CanterburyCorpus())
foreach (object[] testFile in UncompressedTestFiles())
{
yield return new object[] { canterburyWithoutLevel[0], canterburyWithoutLevel[1], compressionLevel };
yield return new object[] { testFile[0], compressionLevel };
}
}
}

public static IEnumerable<object[]> CanterburyCorpus()
{
foreach (int innerIterations in new int[] { 1, 10 })
{
foreach (var fileName in UncompressedTestFiles())
{
yield return new object[] { innerIterations, fileName[0] };
}
}
}


/// <summary>
/// Benchmark tests to measure the performance of individually compressing each file in the
/// Canterbury Corpus
/// </summary>
[Benchmark]
[MemberData(nameof(CanterburyCorpus_WithCompressionLevel))]
public void Compress_Canterbury(int innerIterations, string uncompressedFileName, CompressionLevel compressLevel)
[Benchmark(InnerIterationCount=10)] // limits the max iterations to 100
[MemberData(nameof(UncompressedTestFiles_WithCompressionLevel))]
public void Compress_Canterbury(string uncompressedFileName, CompressionLevel compressLevel)
{
byte[] bytes = File.ReadAllBytes(uncompressedFileName);
MemoryStream[] compressedDataStreams = new MemoryStream[innerIterations];
foreach (var iteration in Benchmark.Iterations)
{
// resizing a memory stream during compression will throw off our results, so pre-size it to the
// size of our input
for (int i = 0; i < innerIterations; i++)
compressedDataStreams[i] = new MemoryStream(bytes.Length);
using (MemoryStream compressedDataStream = new MemoryStream(bytes.Length))
using (iteration.StartMeasurement())
for (int i = 0; i < innerIterations; i++)
using (Stream compressor = CreateStream(compressedDataStreams[i], compressLevel))
compressor.Write(bytes, 0, bytes.Length);

for (int i = 0; i < innerIterations; i++)
compressedDataStreams[i].Dispose();
using (Stream compressor = CreateStream(compressedDataStream, compressLevel))
compressor.Write(bytes, 0, bytes.Length);
}
}

/// <summary>
/// Benchmark tests to measure the performance of individually compressing each file in the
/// Canterbury Corpus
/// </summary>
[Benchmark]
[MemberData(nameof(CanterburyCorpus))]
public void Decompress_Canterbury(int innerIterations, string uncompressedFilePath)
[Benchmark(InnerIterationCount=100)]
[MemberData(nameof(UncompressedTestFiles))]
public void Decompress_Canterbury(string uncompressedFilePath)
{
int innerIterations = (int)Benchmark.InnerIterationCount;
string compressedFilePath = CompressedTestFile(uncompressedFilePath);
byte[] outputRead = new byte[new FileInfo(uncompressedFilePath).Length];
MemoryStream[] memories = new MemoryStream[innerIterations];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,48 +177,6 @@ public async Task ReadAsync_DuringReadAsync()
}
}

[Fact]
public virtual void Dispose_WithUnfinishedWriteAsync()
{
byte[] buffer = new byte[100000];
Random rand = new Random();
rand.NextBytes(buffer);

using (var writeStream = new ManualSyncMemoryStream(false))
{
var compressor = CreateStream(writeStream, CompressionMode.Compress, leaveOpen: true);
compressor.Write(buffer, 0, buffer.Length);
int writesBeingFlushed = 2;
Task task = null;
try
{
// Write needs to be big enough to trigger a write to the underlying base stream so the WriteAsync call doesn't immediately complete.
task = compressor.WriteAsync(buffer, 0, buffer.Length);
while (task.IsCompleted)
{
rand.NextBytes(buffer);
task = compressor.WriteAsync(buffer, 0, buffer.Length);
writesBeingFlushed++;
}

// WriteAsync will be blocked on writing the output to the underlying stream. Calling Dispose will trigger a Finish call with unwritten output
// still available.
Assert.InRange(writeStream.Length, 0, buffer.Length);
compressor.Dispose();
Assert.InRange(writeStream.Length, 0, buffer.Length * writesBeingFlushed);
Assert.False(task.IsCompleted);
}
finally
{
// Unblock Async operations
writeStream.manualResetEvent.Set();
// WriteAsync call will return to the compression stream's WriteAsync which will attempt to
// access members of the now disposed stream.
Assert.Throws<AggregateException>(() => task.Wait(1000));
}
}
}

[Fact]
public virtual async Task Dispose_WithUnfinishedReadAsync()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ public void Precancellation()
}
}

[Fact]
[OuterLoop("Test takes ~12 seconds to run")]
public override void Dispose_WithUnfinishedWriteAsync() { base.Dispose_WithUnfinishedWriteAsync(); }

[Fact]
[OuterLoop("Test takes ~6 seconds to run")]
public override void FlushAsync_DuringWriteAsync() { base.FlushAsync_DuringWriteAsync(); }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,67 +12,48 @@ public class BrotliPerfTests : CompressionTestBase
{
protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br");

public static IEnumerable<object[]> CanterburyCorpus_WithCompressionLevel()
public static IEnumerable<object[]> UncompressedTestFiles_WithCompressionLevel()
{
foreach (CompressionLevel compressionLevel in Enum.GetValues(typeof(CompressionLevel)))
{
foreach (object[] canterburyWithoutLevel in CanterburyCorpus())
foreach (object[] testFile in UncompressedTestFiles())
{
yield return new object[] { canterburyWithoutLevel[0], canterburyWithoutLevel[1], compressionLevel };
yield return new object[] { testFile[0], compressionLevel };
}
}
}

public static IEnumerable<object[]> CanterburyCorpus()
{
foreach (int innerIterations in new int[] { 1, 10 })
{
foreach (var fileName in UncompressedTestFiles())
{
yield return new object[] { innerIterations, fileName[0] };
}
}
}

[Benchmark]
[MemberData(nameof(CanterburyCorpus_WithCompressionLevel))]
public void Compress_Canterbury_WithState(int innerIterations, string uncompressedFileName, CompressionLevel compressLevel)
[Benchmark(InnerIterationCount=10)] // limits the max iterations to 100
[MemberData(nameof(UncompressedTestFiles_WithCompressionLevel))]
public void Compress_Canterbury_WithState(string uncompressedFileName, CompressionLevel compressLevel)
{
byte[] bytes = File.ReadAllBytes(uncompressedFileName);
ReadOnlySpan<byte> uncompressedData = new ReadOnlySpan<byte>(bytes);
int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length);
List<byte[]> compressedDataArrays = new List<byte[]>(innerIterations);
byte[] compressedDataArray = new byte[maxCompressedSize];
foreach (var iteration in Benchmark.Iterations)
{
for (int i = 0; i < innerIterations; i++)
{
compressedDataArrays.Add(new byte[maxCompressedSize]);
}
using (iteration.StartMeasurement())
using (BrotliEncoder encoder = new BrotliEncoder())
{
for (int i = 0; i < innerIterations; i++)
Span<byte> output = new Span<byte>(compressedDataArray);
ReadOnlySpan<byte> input = uncompressedData;
while (!input.IsEmpty && !output.IsEmpty)
{
using (BrotliEncoder encoder = new BrotliEncoder())
{
Span<byte> output = new Span<byte>(compressedDataArrays[i]);
ReadOnlySpan<byte> input = uncompressedData;
while (!input.IsEmpty && !output.IsEmpty)
{
encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock:false);
input = input.Slice(bytesConsumed);
output = output.Slice(written);
}
encoder.Compress(input, output, out int bytesConsumed2, out int written2, isFinalBlock: true);
}
encoder.Compress(input, output, out int bytesConsumed, out int written, isFinalBlock:false);
input = input.Slice(bytesConsumed);
output = output.Slice(written);
}
encoder.Compress(input, output, out int bytesConsumed2, out int written2, isFinalBlock: true);
}
}
}

[Benchmark]
[MemberData(nameof(CanterburyCorpus))]
public void Decompress_Canterbury_WithState(int innerIterations, string uncompressedFileName)
[Benchmark(InnerIterationCount=100)]
[MemberData(nameof(UncompressedTestFiles))]
public void Decompress_Canterbury_WithState(string uncompressedFileName)
{
int innerIterations = (int)Benchmark.InnerIterationCount;
byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(uncompressedFileName));
ReadOnlySpan<byte> compressedData = new ReadOnlySpan<byte>(compressedBytes);
List<byte[]> uncompressedDataArrays = new List<byte[]>(innerIterations);
Expand Down Expand Up @@ -102,27 +83,20 @@ public void Decompress_Canterbury_WithState(int innerIterations, string uncompre
}
}

[Benchmark]
[MemberData(nameof(CanterburyCorpus_WithCompressionLevel))]
public void Compress_Canterbury_WithoutState(int innerIterations, string uncompressedFileName, CompressionLevel compressLevel)
[Benchmark(InnerIterationCount=10)] // limits the max iterations to 100
[MemberData(nameof(UncompressedTestFiles_WithCompressionLevel))]
public void Compress_Canterbury_WithoutState(string uncompressedFileName, CompressionLevel compressLevel)
{
byte[] bytes = File.ReadAllBytes(uncompressedFileName);
ReadOnlySpan<byte> uncompressedData = new ReadOnlySpan<byte>(bytes);
int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length);
List<byte[]> compressedDataArrays = new List<byte[]>(innerIterations);
byte[] compressedDataArray = new byte[maxCompressedSize];
int compressLevelBrotli = compressLevel == CompressionLevel.Optimal ? 11 : compressLevel == CompressionLevel.Fastest ? 1 : 0;
foreach (var iteration in Benchmark.Iterations)
{
for (int i = 0; i < innerIterations; i++)
{
compressedDataArrays.Add(new byte[maxCompressedSize]);
}
using (iteration.StartMeasurement())
{
for (int i = 0; i < innerIterations; i++)
{
Assert.True(BrotliEncoder.TryCompress(uncompressedData, compressedDataArrays[i], out int bytesWritten, compressLevelBrotli, 22));
}
Assert.True(BrotliEncoder.TryCompress(uncompressedData, compressedDataArray, out int bytesWritten, compressLevelBrotli, 22));
}
}
}
Expand All @@ -131,10 +105,11 @@ public void Compress_Canterbury_WithoutState(int innerIterations, string uncompr
/// The perf tests for the instant decompression aren't exactly indicative of real-world scenarios since they require you to know
/// either the exact figure or the upper bound of the uncompressed size of your given compressed data.
/// </summary>
[Benchmark]
[MemberData(nameof(CanterburyCorpus))]
public void Decompress_Canterbury_WithoutState(int innerIterations, string uncompressedFileName)
[Benchmark(InnerIterationCount=100)]
[MemberData(nameof(UncompressedTestFiles))]
public void Decompress_Canterbury_WithoutState(string uncompressedFileName)
{
int innerIterations = (int)Benchmark.InnerIterationCount;
byte[] compressedBytes = File.ReadAllBytes(CompressedTestFile(uncompressedFileName));
ReadOnlySpan<byte> compressedData = new ReadOnlySpan<byte>(compressedBytes);
int uncompressedSize = (int)new FileInfo(uncompressedFileName).Length;
Expand All @@ -153,6 +128,6 @@ public void Decompress_Canterbury_WithoutState(int innerIterations, string uncom
}
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
<ItemGroup>
<!-- [ActiveIssue(26566)]
<Compile Include="BrotliPerfTests.cs" />
<Compile Include="CompressionStreamPerfTests.Brotli.cs" />
<Compile Include="$(CommonTestPath)\System\IO\Compression\CompressionStreamTestBase.cs">
Expand All @@ -20,7 +19,6 @@
<Compile Include="$(CommonTestPath)\System\IO\Compression\CompressionStreamPerfTestBase.cs">
<Link>Common\System\IO\Compression\CompressionStreamPerfTestBase.cs</Link>
</Compile>
-->
</ItemGroup>
<ItemGroup>
<SupplementalTestData Include="$(PackagesDir)system.io.compression.testdata\1.0.6-prerelease\content\**\*.*">
Expand Down