From a82c9ed5f64dbe7be4896fd963139f79a32fad99 Mon Sep 17 00:00:00 2001 From: Jeremy Kuhne Date: Thu, 6 Sep 2018 18:11:06 -0700 Subject: [PATCH] Add perf tests to System.IO (dotnet/corefx#31552) * Add perf tests to System.IO Add tests for measuring format writes for StreamWriter. * Add a test validating dispatching of format calls when overridden. Commit migrated from https://github.com/dotnet/corefx/commit/1e1f421c8e57cbd317800e0a10287488bb05c808 --- src/libraries/System.IO/System.IO.sln | 24 +++-- .../tests/Performance/Configurations.props | 8 ++ .../tests/Performance/Perf.StreamWriter.cs | 116 +++++++++++++++++++++ .../Performance/System.IO.Performance.Tests.csproj | 30 ++++++ .../System.IO/tests/StreamWriter/StreamWriter.cs | 47 +++++++++ 5 files changed, 218 insertions(+), 7 deletions(-) create mode 100644 src/libraries/System.IO/tests/Performance/Configurations.props create mode 100644 src/libraries/System.IO/tests/Performance/Perf.StreamWriter.cs create mode 100644 src/libraries/System.IO/tests/Performance/System.IO.Performance.Tests.csproj diff --git a/src/libraries/System.IO/System.IO.sln b/src/libraries/System.IO/System.IO.sln index 9fcc875..b2365e9 100644 --- a/src/libraries/System.IO/System.IO.sln +++ b/src/libraries/System.IO/System.IO.sln @@ -4,10 +4,15 @@ VisualStudioVersion = 15.0.27213.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Tests", "tests\System.IO.Tests.csproj", "{492EC54D-D2C4-4B3F-AC1F-646B3F7EBB02}" ProjectSection(ProjectDependencies) = postProject - {07390899-C8F6-4e83-A3A9-6867B8CB46A0} = {07390899-C8F6-4e83-A3A9-6867B8CB46A0} + {07390899-C8F6-4E83-A3A9-6867B8CB46A0} = {07390899-C8F6-4E83-A3A9-6867B8CB46A0} EndProjectSection EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO", "src\System.IO.csproj", "{07390899-C8F6-4e83-A3A9-6867B8CB46A0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Performance.Tests", "tests\Performance\System.IO.Performance.Tests.csproj", "{66AE57BA-B56C-4A1E-ACA6-7C18431D416B}" + ProjectSection(ProjectDependencies) = postProject + {07390899-C8F6-4E83-A3A9-6867B8CB46A0} = {07390899-C8F6-4E83-A3A9-6867B8CB46A0} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO", "src\System.IO.csproj", "{07390899-C8F6-4E83-A3A9-6867B8CB46A0}" ProjectSection(ProjectDependencies) = postProject {88883C57-83BE-4E93-A363-4CFC716F248F} = {88883C57-83BE-4E93-A363-4CFC716F248F} EndProjectSection @@ -30,10 +35,14 @@ Global {492EC54D-D2C4-4B3F-AC1F-646B3F7EBB02}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU {492EC54D-D2C4-4B3F-AC1F-646B3F7EBB02}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU {492EC54D-D2C4-4B3F-AC1F-646B3F7EBB02}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU - {07390899-C8F6-4e83-A3A9-6867B8CB46A0}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU - {07390899-C8F6-4e83-A3A9-6867B8CB46A0}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU - {07390899-C8F6-4e83-A3A9-6867B8CB46A0}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU - {07390899-C8F6-4e83-A3A9-6867B8CB46A0}.Release|Any CPU.Build.0 = netcoreapp-Release|Any CPU + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B}.Debug|Any CPU.ActiveCfg = netstandard-Debug|Any CPU + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B}.Debug|Any CPU.Build.0 = netstandard-Debug|Any CPU + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B}.Release|Any CPU.ActiveCfg = netstandard-Release|Any CPU + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B}.Release|Any CPU.Build.0 = netstandard-Release|Any CPU + {07390899-C8F6-4E83-A3A9-6867B8CB46A0}.Debug|Any CPU.ActiveCfg = uapaot-Windows_NT-Debug|Any CPU + {07390899-C8F6-4E83-A3A9-6867B8CB46A0}.Debug|Any CPU.Build.0 = uapaot-Windows_NT-Debug|Any CPU + {07390899-C8F6-4E83-A3A9-6867B8CB46A0}.Release|Any CPU.ActiveCfg = uap-Windows_NT-Release|Any CPU + {07390899-C8F6-4E83-A3A9-6867B8CB46A0}.Release|Any CPU.Build.0 = uap-Windows_NT-Release|Any CPU {88883C57-83BE-4E93-A363-4CFC716F248F}.Debug|Any CPU.ActiveCfg = netcoreapp-Debug|Any CPU {88883C57-83BE-4E93-A363-4CFC716F248F}.Debug|Any CPU.Build.0 = netcoreapp-Debug|Any CPU {88883C57-83BE-4E93-A363-4CFC716F248F}.Release|Any CPU.ActiveCfg = netcoreapp-Release|Any CPU @@ -44,7 +53,8 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {492EC54D-D2C4-4B3F-AC1F-646B3F7EBB02} = {1A2F9F4A-A032-433E-B914-ADD5992BB178} - {07390899-C8F6-4e83-A3A9-6867B8CB46A0} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD} + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B} = {1A2F9F4A-A032-433E-B914-ADD5992BB178} + {07390899-C8F6-4E83-A3A9-6867B8CB46A0} = {E107E9C1-E893-4E87-987E-04EF0DCEAEFD} {88883C57-83BE-4E93-A363-4CFC716F248F} = {2E666815-2EDB-464B-9DF6-380BF4789AD4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/src/libraries/System.IO/tests/Performance/Configurations.props b/src/libraries/System.IO/tests/Performance/Configurations.props new file mode 100644 index 0000000..78953df --- /dev/null +++ b/src/libraries/System.IO/tests/Performance/Configurations.props @@ -0,0 +1,8 @@ + + + + + netstandard; + + + diff --git a/src/libraries/System.IO/tests/Performance/Perf.StreamWriter.cs b/src/libraries/System.IO/tests/Performance/Perf.StreamWriter.cs new file mode 100644 index 0000000..b33202f --- /dev/null +++ b/src/libraries/System.IO/tests/Performance/Perf.StreamWriter.cs @@ -0,0 +1,116 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.Xunit.Performance; + +namespace System.IO.Tests +{ + public class Perf_StreamWriter + { + [Benchmark(InnerIterationCount = 20000)] + public void Write_Format_OneArg() + { + // Don't want MemoryStream to be expandable to avoid measuring resize + MemoryStream memory = new MemoryStream(new byte[1024 * 1024]); + StreamWriter writer = new StreamWriter(memory); + + foreach (var iteration in Benchmark.Iterations) + { + memory.Position = 0; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + writer.Write("Performance test iteration {0}", i); + } + } + writer.Flush(); + } + } + + [Benchmark(InnerIterationCount = 20000)] + public void Write_Format_OneNoBoxArg() + { + // Don't want MemoryStream to be expandable to avoid measuring resize + MemoryStream memory = new MemoryStream(new byte[1024 * 1024]); + StreamWriter writer = new StreamWriter(memory); + + foreach (var iteration in Benchmark.Iterations) + { + memory.Position = 0; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + writer.Write("Performance test: {0}", nameof(Write_Format_OneNoBoxArg)); + } + } + writer.Flush(); + } + } + + [Benchmark(InnerIterationCount = 20000)] + public void WriteLine_Format_OneArg() + { + // Don't want MemoryStream to be expandable to avoid measuring resize + MemoryStream memory = new MemoryStream(new byte[1024 * 1024]); + StreamWriter writer = new StreamWriter(memory); + + foreach (var iteration in Benchmark.Iterations) + { + memory.Position = 0; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + writer.WriteLine("Performance test iteration {0}", i); + } + } + writer.Flush(); + } + } + + [Benchmark(InnerIterationCount = 20000)] + public void Write_Format_Params() + { + // Don't want MemoryStream to be expandable to avoid measuring resize + MemoryStream memory = new MemoryStream(new byte[1024 * 1024]); + StreamWriter writer = new StreamWriter(memory); + + foreach (var iteration in Benchmark.Iterations) + { + memory.Position = 0; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + writer.Write("Performance test iteration {0}", i, i, i, i, i); + } + } + writer.Flush(); + } + } + + [Benchmark(InnerIterationCount = 20000)] + public void WriteLine_Format_Params() + { + // Don't want MemoryStream to be expandable to avoid measuring resize + MemoryStream memory = new MemoryStream(new byte[1024 * 1024]); + StreamWriter writer = new StreamWriter(memory); + + foreach (var iteration in Benchmark.Iterations) + { + memory.Position = 0; + using (iteration.StartMeasurement()) + { + for (int i = 0; i < Benchmark.InnerIterationCount; i++) + { + writer.WriteLine("Performance test iteration {0}", i, i, i, i, i); + } + } + writer.Flush(); + } + } + } +} diff --git a/src/libraries/System.IO/tests/Performance/System.IO.Performance.Tests.csproj b/src/libraries/System.IO/tests/Performance/System.IO.Performance.Tests.csproj new file mode 100644 index 0000000..1e04191 --- /dev/null +++ b/src/libraries/System.IO/tests/Performance/System.IO.Performance.Tests.csproj @@ -0,0 +1,30 @@ + + + InnerLoop;OuterLoop + true + {66AE57BA-B56C-4A1E-ACA6-7C18431D416B} + netstandard-Debug;netstandard-Release + + + + {69e46a6f-9966-45a5-8945-2559fe337827} + RemoteExecutorConsoleApp + + + Common\System\PerfUtils.cs + + + Common\System\IO\PathFeatures.cs + + + + + + {69e46a6f-9966-45a5-8945-2559fe337827} + PerfRunner + + + + + + \ No newline at end of file diff --git a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.cs b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.cs index 25ce586..c4969c8 100644 --- a/src/libraries/System.IO/tests/StreamWriter/StreamWriter.cs +++ b/src/libraries/System.IO/tests/StreamWriter/StreamWriter.cs @@ -27,5 +27,52 @@ namespace System.IO.Tests Assert.Equal("apppad", reader.ReadLine()); } } + + private class TestFormatWriter : StreamWriter + { + public int WriteCalls { get; private set; } + public int WriteLineCalls { get; private set; } + + public TestFormatWriter(Stream stream) : base(stream) + { } + + public override void Write(string value) + { + WriteCalls++; + base.Write(value); + } + + public override void WriteLine(string value) + { + WriteLineCalls++; + base.WriteLine(value); + } + } + + [Fact] + public void FormatOverloadsCallWrite() + { + TestFormatWriter writer = new TestFormatWriter(new MemoryStream()); + writer.Write("{0}", "Zero"); + Assert.Equal(1, writer.WriteCalls); + writer.Write("{0}{1}", "Zero", "One"); + Assert.Equal(2, writer.WriteCalls); + writer.Write("{0}{1}{2}", "Zero", "One", "Two"); + Assert.Equal(3, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + Assert.Equal(4, writer.WriteCalls); + writer.Write("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + Assert.Equal(5, writer.WriteCalls); + writer.WriteLine("{0}", "Zero"); + Assert.Equal(1, writer.WriteLineCalls); + writer.WriteLine("{0}{1}", "Zero", "One"); + Assert.Equal(2, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}", "Zero", "One", "Two"); + Assert.Equal(3, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}", "Zero", "One", "Two", "Three"); + Assert.Equal(4, writer.WriteLineCalls); + writer.WriteLine("{0}{1}{2}{3}{4}", "Zero", "One", "Two", "Three", "Four"); + Assert.Equal(5, writer.WriteLineCalls); + } } } -- 2.7.4