diff --git a/src/Common/tests/System/IO/Compression/CompressionStreamPerfTestBase.cs b/src/Common/tests/System/IO/Compression/CompressionStreamPerfTestBase.cs index 43af3eb4df33..aaba3178587d 100644 --- a/src/Common/tests/System/IO/Compression/CompressionStreamPerfTestBase.cs +++ b/src/Common/tests/System/IO/Compression/CompressionStreamPerfTestBase.cs @@ -10,52 +10,34 @@ namespace System.IO.Compression { public abstract class CompressionStreamPerfTestBase : CompressionStreamTestBase { - public static IEnumerable CanterburyCorpus_WithCompressionLevel() + public static IEnumerable 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 CanterburyCorpus() - { - foreach (int innerIterations in new int[] { 1, 10 }) - { - foreach (var fileName in UncompressedTestFiles()) - { - yield return new object[] { innerIterations, fileName[0] }; - } - } - } - - /// /// Benchmark tests to measure the performance of individually compressing each file in the /// Canterbury Corpus /// - [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); } } @@ -63,10 +45,11 @@ public void Compress_Canterbury(int innerIterations, string uncompressedFileName /// Benchmark tests to measure the performance of individually compressing each file in the /// Canterbury Corpus /// - [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]; diff --git a/src/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs b/src/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs index e6585de33abf..9014d94c5c69 100644 --- a/src/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs +++ b/src/Common/tests/System/IO/Compression/CompressionStreamUnitTestBase.cs @@ -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(() => task.Wait(1000)); - } - } - } - [Fact] public virtual async Task Dispose_WithUnfinishedReadAsync() { diff --git a/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs b/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs index e7323ff93648..84db45dc53fc 100644 --- a/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs +++ b/src/System.IO.Compression.Brotli/tests/CompressionStreamUnitTests.Brotli.cs @@ -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(); } diff --git a/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs b/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs index f0ee2b7d2235..410b6cc14b8e 100644 --- a/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs +++ b/src/System.IO.Compression.Brotli/tests/Performance/BrotliPerfTests.cs @@ -12,67 +12,48 @@ public class BrotliPerfTests : CompressionTestBase { protected override string CompressedTestFile(string uncompressedPath) => Path.Combine("BrotliTestData", Path.GetFileName(uncompressedPath) + ".br"); - public static IEnumerable CanterburyCorpus_WithCompressionLevel() + public static IEnumerable 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 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 uncompressedData = new ReadOnlySpan(bytes); int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length); - List compressedDataArrays = new List(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 output = new Span(compressedDataArray); + ReadOnlySpan input = uncompressedData; + while (!input.IsEmpty && !output.IsEmpty) { - using (BrotliEncoder encoder = new BrotliEncoder()) - { - Span output = new Span(compressedDataArrays[i]); - ReadOnlySpan 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 compressedData = new ReadOnlySpan(compressedBytes); List uncompressedDataArrays = new List(innerIterations); @@ -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 uncompressedData = new ReadOnlySpan(bytes); int maxCompressedSize = BrotliEncoder.GetMaxCompressedLength(bytes.Length); - List compressedDataArrays = new List(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)); } } } @@ -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. /// - [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 compressedData = new ReadOnlySpan(compressedBytes); int uncompressedSize = (int)new FileInfo(uncompressedFileName).Length; @@ -153,6 +128,6 @@ public void Decompress_Canterbury_WithoutState(int innerIterations, string uncom } } } - } + } } } diff --git a/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj b/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj index 1d8d0cdc7036..85e6b196f896 100644 --- a/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj +++ b/src/System.IO.Compression.Brotli/tests/Performance/System.IO.Compression.Brotli.Performance.Tests.csproj @@ -11,7 +11,6 @@ -