Add perf tests to System.IO (dotnet/corefx#31552)
authorJeremy Kuhne <jeremy.kuhne@microsoft.com>
Fri, 7 Sep 2018 01:11:06 +0000 (18:11 -0700)
committerGitHub <noreply@github.com>
Fri, 7 Sep 2018 01:11:06 +0000 (18:11 -0700)
* 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
src/libraries/System.IO/tests/Performance/Configurations.props [new file with mode: 0644]
src/libraries/System.IO/tests/Performance/Perf.StreamWriter.cs [new file with mode: 0644]
src/libraries/System.IO/tests/Performance/System.IO.Performance.Tests.csproj [new file with mode: 0644]
src/libraries/System.IO/tests/StreamWriter/StreamWriter.cs

index 9fcc875..b2365e9 100644 (file)
@@ -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 (file)
index 0000000..78953df
--- /dev/null
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup>
+    <BuildConfigurations>
+      netstandard;
+    </BuildConfigurations>
+  </PropertyGroup>
+</Project>
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 (file)
index 0000000..b33202f
--- /dev/null
@@ -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 (file)
index 0000000..1e04191
--- /dev/null
@@ -0,0 +1,30 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TestCategories>InnerLoop;OuterLoop</TestCategories>
+    <IncludePerformanceTests>true</IncludePerformanceTests>
+    <ProjectGuid>{66AE57BA-B56C-4A1E-ACA6-7C18431D416B}</ProjectGuid>
+    <Configurations>netstandard-Debug;netstandard-Release</Configurations>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(CommonTestPath)\System\Diagnostics\RemoteExecutorConsoleApp\RemoteExecutorConsoleApp.csproj">
+      <Project>{69e46a6f-9966-45a5-8945-2559fe337827}</Project>
+      <Name>RemoteExecutorConsoleApp</Name>
+    </ProjectReference>
+    <Compile Include="$(CommonTestPath)\System\PerfUtils.cs">
+      <Link>Common\System\PerfUtils.cs</Link>
+    </Compile>
+    <Compile Include="$(CommonTestPath)\System\IO\PathFeatures.cs">
+      <Link>Common\System\IO\PathFeatures.cs</Link>
+    </Compile>
+    <Compile Include="Perf.StreamWriter.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="$(CommonPath)\..\perf\PerfRunner\PerfRunner.csproj">
+      <Project>{69e46a6f-9966-45a5-8945-2559fe337827}</Project>
+      <Name>PerfRunner</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+</Project>
\ No newline at end of file
index 25ce586..c4969c8 100644 (file)
@@ -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);
+        }
     }
 }