From e44a32156ecd8a1a948d88c8587f2016b05dc18a Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Thu, 16 May 2019 19:52:32 -0700 Subject: [PATCH 1/7] Add missing tests from .NET Core 3.0 perf tests blog post --- .../corefx/System.Buffers/Utf8ParserTests.cs | 2 +- .../System.Collections/Concurrent/Count.cs | 13 +++++- .../SortedSet/Perf_SortedSet.cs | 8 ++++ .../Perf.DateTimeCultureInfo.cs | 16 ++++++- .../micro/corefx/System.Linq/Perf.Linq.cs | 9 ++++ .../corefx/System.Memory/ReadOnlySpan.cs | 13 +++++- .../Perf.SocketsHttpHandler.cs | 23 ++++++---- .../PhysicalAddressTests.cs | 23 ++++++++++ .../corefx/System.Net.Primitives/DnsTests.cs | 19 +++++++++ .../Perf.StreamWriter.cs | 14 ++----- .../Perf.WebUtility.cs | 8 ++-- .../SafeHandleTests.cs | 35 ++++++++++++++++ .../micro/corefx/System.Runtime/Perf.Array.cs | 42 +++++++++++++++++++ .../micro/corefx/System.Runtime/Perf.Char.cs | 11 +++++ .../corefx/System.Runtime/Perf.DateTime.cs | 6 +++ .../corefx/System.Runtime/Perf.Decimal.cs | 24 +++++++++++ .../micro/corefx/System.Runtime/Perf.Enum.cs | 16 +++++++ .../micro/corefx/System.Runtime/Perf.Guid.cs | 20 +++++++++ .../micro/corefx/System.Runtime/Perf.Int32.cs | 21 +++++++--- .../corefx/System.Runtime/Perf.String.cs | 16 +++++++ .../micro/corefx/System.Runtime/Perf.Uri.cs | 3 ++ .../X509Certificate2Tests.cs | 34 +++++++++++++++ .../Perf.AsyncMethods.cs | 9 ++++ .../System.Threading.Timers/Perf.Timer.cs | 26 ++++++++++++ .../Perf.CancellationToken.cs | 9 ++++ .../corefx/System.Threading/Perf.Thread.cs | 16 +++++++ 26 files changed, 403 insertions(+), 33 deletions(-) create mode 100644 src/benchmarks/micro/corefx/System.Net.NetworkInformation/PhysicalAddressTests.cs create mode 100644 src/benchmarks/micro/corefx/System.Net.Primitives/DnsTests.cs create mode 100644 src/benchmarks/micro/corefx/System.Runtime.InteropServices/SafeHandleTests.cs create mode 100644 src/benchmarks/micro/corefx/System.Security.Cryptography.X509Certificates/X509Certificate2Tests.cs create mode 100644 src/benchmarks/micro/corefx/System.Threading/Perf.Thread.cs diff --git a/src/benchmarks/micro/corefx/System.Buffers/Utf8ParserTests.cs b/src/benchmarks/micro/corefx/System.Buffers/Utf8ParserTests.cs index 6097e1a81dd..b46951e0751 100644 --- a/src/benchmarks/micro/corefx/System.Buffers/Utf8ParserTests.cs +++ b/src/benchmarks/micro/corefx/System.Buffers/Utf8ParserTests.cs @@ -36,7 +36,7 @@ public IEnumerable UInt64HexValues public bool TryParseUInt64Hex(Utf8TestCase value) => Utf8Parser.TryParse(value.Utf8Bytes, out ulong _, out int _, 'X'); public IEnumerable Int32Values - => Perf_Int32.StringValues.OfType().Select(formatted => new Utf8TestCase(formatted)); + => Perf_Int32.StringValuesDecimal.OfType().Select(formatted => new Utf8TestCase(formatted)); [Benchmark] [ArgumentsSource(nameof(Int32Values))] diff --git a/src/benchmarks/micro/corefx/System.Collections/Concurrent/Count.cs b/src/benchmarks/micro/corefx/System.Collections/Concurrent/Count.cs index 746fab06e29..b29a1752dad 100644 --- a/src/benchmarks/micro/corefx/System.Collections/Concurrent/Count.cs +++ b/src/benchmarks/micro/corefx/System.Collections/Concurrent/Count.cs @@ -38,11 +38,20 @@ public void Setup() [Benchmark] public int Queue() => _queue.Count; - + + [Benchmark] + public int Queue_EnqueueCountDequeue() + { + _queue.Enqueue(default); + int c = _queue.Count; + _queue.TryDequeue(out _); + return c; + } + [Benchmark] public int Stack() => _stack.Count; [Benchmark] public int Bag() => _bag.Count; } -} \ No newline at end of file +} diff --git a/src/benchmarks/micro/corefx/System.Collections/SortedSet/Perf_SortedSet.cs b/src/benchmarks/micro/corefx/System.Collections/SortedSet/Perf_SortedSet.cs index 9d0a63e04fa..1a9f12ab008 100644 --- a/src/benchmarks/micro/corefx/System.Collections/SortedSet/Perf_SortedSet.cs +++ b/src/benchmarks/micro/corefx/System.Collections/SortedSet/Perf_SortedSet.cs @@ -28,5 +28,13 @@ public void Setup() [Benchmark] public int Max() => _set.Max; + + [Benchmark] + public int EnumerateViewBetween() + { + int count = 0; + foreach (int item in _set.GetViewBetween(100, 200)) count++; + return count; + } } } diff --git a/src/benchmarks/micro/corefx/System.Globalization/Perf.DateTimeCultureInfo.cs b/src/benchmarks/micro/corefx/System.Globalization/Perf.DateTimeCultureInfo.cs index 75ecb0f3480..2a6ce01d751 100644 --- a/src/benchmarks/micro/corefx/System.Globalization/Perf.DateTimeCultureInfo.cs +++ b/src/benchmarks/micro/corefx/System.Globalization/Perf.DateTimeCultureInfo.cs @@ -16,8 +16,8 @@ namespace System.Globalization.Tests [BenchmarkCategory(Categories.CoreFX)] public class Perf_DateTimeCultureInfo { - private readonly DateTime _time = DateTime.Now; - + private readonly DateTime _time = new DateTime(654321098765432109); + public IEnumerable Cultures() { yield return new CultureInfo("fr"); @@ -35,5 +35,17 @@ public IEnumerable Cultures() [ArgumentsSource(nameof(Cultures))] public DateTime Parse(CultureInfo culturestring) => DateTime.Parse("10/10/2010 12:00:00 AM", culturestring); + + private readonly CultureInfo _hebrewIsrael = CreateHebrewIsraelCultureInfo(); + + private static CultureInfo CreateHebrewIsraelCultureInfo() + { + var c = new CultureInfo("he-IL"); + c.DateTimeFormat.Calendar = new HebrewCalendar(); + return c; + } + + [Benchmark] + public string ToStringHebrewIsrael() => _time.ToString(_hebrewIsrael); } } diff --git a/src/benchmarks/micro/corefx/System.Linq/Perf.Linq.cs b/src/benchmarks/micro/corefx/System.Linq/Perf.Linq.cs index fd1671fe508..1a78447fb84 100644 --- a/src/benchmarks/micro/corefx/System.Linq/Perf.Linq.cs +++ b/src/benchmarks/micro/corefx/System.Linq/Perf.Linq.cs @@ -51,6 +51,10 @@ private class ChildClass : BaseClass private readonly ChildClass[] _childClassArrayOfTenElements = Enumerable.Repeat(new ChildClass() { Value = 1, ChildValue = 2 }, 10).ToArray(); private readonly int[] _intArrayOfTenElements = Enumerable.Repeat(1, 10).ToArray(); + [Benchmark] + public void EmptyTakeSelectToArray() => + Enumerable.Empty().Take(10).Select(i => i).ToArray(); + [Benchmark] [ArgumentsSource(nameof(IterationSizeWrapperData))] public void Select(int size, int iteration, Perf_LinqTestBase.WrapperType wrapType) @@ -132,6 +136,11 @@ public void OrderByThenBy(int size, int iteration, Perf_LinqTestBase.WrapperType public void Range(int size, int iteration) => Enumerable.Range(0, size).Consume(_consumer); + [Benchmark] + [Arguments(DefaultSize)] + public void RangeSelect(int size) + => Enumerable.Range(0, size).Select(i => i).Consume(_consumer); + [Benchmark] [Arguments(DefaultSize, DefaulIterationCount)] public void Repeat(int size, int iteration) diff --git a/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs b/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs index 8f6c38743ba..defb43098b2 100644 --- a/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs +++ b/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs @@ -73,7 +73,18 @@ public int IndexOfString(string input, string value, StringComparison comparison new object[] { GenerateInputString('\u3060', 1000, 'x', 500), "x", StringComparison.Ordinal }, new object[] { GenerateInputString('\u3060', 100, '\u3059', 50), "\u3059", StringComparison.Ordinal } }; - + + [Benchmark] + [ArgumentsSource(nameof(TrimArguments))] + public ReadOnlySpan Trim(string input) => input.AsSpan().Trim(); + + public static IEnumerable TrimArguments => new List + { + new object[] { "" }, + new object[] { " abcdefg " }, + new object[] { "abcdefg" } + }; + private static string GenerateInputString(char source, int count, char replaceChar, int replacePos) { char[] str = new char[count]; diff --git a/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs b/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs index 281f1d1401d..08f69329e2f 100644 --- a/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs +++ b/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs @@ -20,9 +20,14 @@ namespace System.Net.Http.Tests public class SocketsHttpHandlerPerfTest { // the field names start with lowercase to keep to benchmark ID! do not change it - [Params(false, true)] public bool ssl; - [Params(false, true)] public bool chunkedResponse; - [Params(1, 100_000)] public int responseLength; + [Params(false, true)] + public bool Ssl { get; set; } + + [Params(false, true)] + public bool ChunkedResponse { get; set; } + + [Params(1, 1024, 10 * 1024 * 1024)] + public int ResponseLength { get; set; } private System.Security.Cryptography.X509Certificates.X509Certificate2 _serverCert; private Socket _listener; @@ -40,9 +45,9 @@ public void Setup() _listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); _listener.Listen(int.MaxValue); string responseText = - "HTTP/1.1 200 OK\r\n" + (chunkedResponse ? - $"Transfer-Encoding: chunked\r\n\r\n{responseLength.ToString("X")}\r\n{new string('a', responseLength)}\r\n0\r\n\r\n" : - $"Content-Length: {responseLength}\r\n\r\n{new string('a', responseLength)}"); + "HTTP/1.1 200 OK\r\n" + (ChunkedResponse ? + $"Transfer-Encoding: chunked\r\n\r\n{ResponseLength.ToString("X")}\r\n{new string('a', ResponseLength)}\r\n0\r\n\r\n" : + $"Content-Length: {ResponseLength}\r\n\r\n{new string('a', ResponseLength)}"); ReadOnlyMemory responseBytes = Encoding.UTF8.GetBytes(responseText); _serverTask = Task.Run(async () => @@ -56,7 +61,7 @@ public void Setup() try { Stream stream = new NetworkStream(s); - if (ssl) + if (Ssl) { var sslStream = new SslStream(stream, false, delegate { return true; }); await sslStream.AuthenticateAsServerAsync(_serverCert, false, SslProtocols.None, false); @@ -80,11 +85,11 @@ public void Setup() }); var ep = (IPEndPoint)_listener.LocalEndPoint; - var uri = new Uri($"http{(ssl ? "s" : "")}://{ep.Address}:{ep.Port}/"); + var uri = new Uri($"http{(Ssl ? "s" : "")}://{ep.Address}:{ep.Port}/"); _handler = new SocketsHttpHandler(); _invoker = new HttpMessageInvoker(_handler); - if (ssl) + if (Ssl) { _handler.SslOptions.RemoteCertificateValidationCallback = delegate { return true; }; } diff --git a/src/benchmarks/micro/corefx/System.Net.NetworkInformation/PhysicalAddressTests.cs b/src/benchmarks/micro/corefx/System.Net.NetworkInformation/PhysicalAddressTests.cs new file mode 100644 index 00000000000..caa5ff61304 --- /dev/null +++ b/src/benchmarks/micro/corefx/System.Net.NetworkInformation/PhysicalAddressTests.cs @@ -0,0 +1,23 @@ +// 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 System.Linq; +using BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace System.Net.NetworkInformation.Tests +{ + [BenchmarkCategory(Categories.CoreFX)] + public class PhysicalAddressTests + { + private readonly PhysicalAddress _short = new PhysicalAddress(new byte[1] { 42 }); + private readonly PhysicalAddress _long = new PhysicalAddress(Enumerable.Range(0, 256).Select(i => (byte)i).ToArray()); + + [Benchmark] + public void PAShort() => _short.ToString(); + + [Benchmark] + public void PALong() => _long.ToString(); + } +} diff --git a/src/benchmarks/micro/corefx/System.Net.Primitives/DnsTests.cs b/src/benchmarks/micro/corefx/System.Net.Primitives/DnsTests.cs new file mode 100644 index 00000000000..8da50bc51cf --- /dev/null +++ b/src/benchmarks/micro/corefx/System.Net.Primitives/DnsTests.cs @@ -0,0 +1,19 @@ +// 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 BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace System.Net.Tests +{ + [BenchmarkCategory(Categories.CoreFX)] + public class DnsTests + { + [Benchmark] + public IPHostEntry GetHostEntry() => Dns.GetHostEntry("34.206.253.53"); + + [Benchmark] + public string GetHostName() => Dns.GetHostName(); + } +} diff --git a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs index 86275165aa1..c32cefbbbb9 100644 --- a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs +++ b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs @@ -19,7 +19,6 @@ public class Perf_StreamWriter private string _string2 = new string('a', 2), _string100 = new string('a', 100); private char[] _buffer2 = new string('a', 2).ToCharArray(), _buffer100 = new string('a', 100).ToCharArray(); private char[] _buffer12 = new string('a', 12).ToCharArray(), _buffer110 = new string('a', 110).ToCharArray(); - private MemoryStream _memoryStream; private StreamWriter _streamWriter; public IEnumerable WriteLengthMemberData() @@ -31,14 +30,12 @@ public IEnumerable WriteLengthMemberData() [GlobalSetup] public void Setup() { - _memoryStream = new MemoryStream(MemoryStreamSize); - _streamWriter = new StreamWriter(_memoryStream, new UTF8Encoding(false, true), DefaultStreamWriterBufferSize, leaveOpen: true); + _streamWriter = new StreamWriter(Stream.Null, new UTF8Encoding(false, true), DefaultStreamWriterBufferSize, leaveOpen: true); } [GlobalCleanup] public void Cleanup() { - _memoryStream.Dispose(); _streamWriter.Dispose(); } @@ -51,7 +48,6 @@ public void WriteCharArray(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; - var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -60,7 +56,6 @@ public void WriteCharArray(int writeLength) writer.Write(buffer); } writer.Flush(); - stream.Position = 0; } } @@ -73,7 +68,6 @@ public void WritePartialCharArray(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; - var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -82,7 +76,6 @@ public void WritePartialCharArray(int writeLength) writer.Write(buffer, 10, writeLength); } writer.Flush(); - stream.Position = 0; } } @@ -95,7 +88,6 @@ public void WriteString(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; - var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -104,8 +96,10 @@ public void WriteString(int writeLength) writer.Write(value); } writer.Flush(); - stream.Position = 0; } } + + [Benchmark] + public void WriteFormat() => _streamWriter.Write("Writing out a value: {0}", 42); } } diff --git a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs index 5da5ccf1467..1d3485ee238 100644 --- a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs +++ b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs @@ -4,7 +4,6 @@ using BenchmarkDotNet.Attributes; using MicroBenchmarks; -using System.Net; namespace System.Net.Tests { @@ -12,9 +11,12 @@ namespace System.Net.Tests public class Perf_WebUtility { [Benchmark] - public string Decode_DecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxy%22"); + public string UrlDecode_DecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxy%22"); [Benchmark] - public string Decode_NoDecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxyz"); + public string UrlDecode_NoDecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxyz"); + + [Benchmark] + public void HtmlDecode_Entities() => WebUtility.HtmlDecode("水水水水水水水"); } } diff --git a/src/benchmarks/micro/corefx/System.Runtime.InteropServices/SafeHandleTests.cs b/src/benchmarks/micro/corefx/System.Runtime.InteropServices/SafeHandleTests.cs new file mode 100644 index 00000000000..7a0ec88796a --- /dev/null +++ b/src/benchmarks/micro/corefx/System.Runtime.InteropServices/SafeHandleTests.cs @@ -0,0 +1,35 @@ +// 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 BenchmarkDotNet.Attributes; +using MicroBenchmarks; +using Microsoft.Win32.SafeHandles; + +namespace System.Runtime.InteropServices.Tests +{ + [BenchmarkCategory(Categories.CoreFX)] + public class SafeHandleTests + { + private readonly SafeFileHandle _sfh = new SafeFileHandle((IntPtr)12345, ownsHandle: false); + + [Benchmark] + public IntPtr AddRef_GetHandle_Release() + { + bool success = false; + try + { + _sfh.DangerousAddRef(ref success); + return _sfh.DangerousGetHandle(); + } + finally + { + if (success) + { + _sfh.DangerousRelease(); + } + } + } + + } +} diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Array.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Array.cs index a077b2b269c..87ee07d3b38 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Array.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Array.cs @@ -4,6 +4,8 @@ using BenchmarkDotNet.Attributes; using MicroBenchmarks; +using System.Linq; +using System.Runtime.InteropServices; namespace System.Tests { @@ -270,5 +272,45 @@ public void ArrayResize() for (int i = 0; i < _byteArrays.Length; i++) Array.Resize(ref _byteArrays[i], NewSize); } + + private readonly int[] _reversibleArray = Enumerable.Range(0, 256).ToArray(); + + [Benchmark] + public void Reverse() => Array.Reverse(_reversibleArray); + + [GlobalSetup(Target = nameof(ClearUnaligned))] + public void SetupClearUnaligned() + { + while (true) + { + var buffer = new byte[8192]; + GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); + if (((long)handle.AddrOfPinnedObject()) % 32 != 0) + { + _clearableArrayHandle = handle; + _clearableArray = buffer; + return; + } + handle.Free(); + } + } + + [GlobalCleanup(Target = nameof(ClearUnaligned))] + public void CleanupClearUnaligned() => _clearableArrayHandle.Free(); + + private GCHandle _clearableArrayHandle; + private byte[] _clearableArray; + + [Benchmark] + public void ClearUnaligned() => Array.Clear(_clearableArray, 0, _clearableArray.Length); + + private readonly char[] _indexOfCharArray = "This is a test of a reasonably long string to see how IndexOf works".ToCharArray(); + private readonly short[] _indexOfShortArray = "This is a test of a reasonably long string to see how IndexOf works".Select(c => (short)c).ToArray(); + + [Benchmark] + public int IndexOfChar() => Array.IndexOf(_indexOfCharArray, '.'); + + [Benchmark] + public void IndexOfShort() => Array.IndexOf(_indexOfShortArray, (short)'.'); } } \ No newline at end of file diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Char.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Char.cs index 68d7c2ced76..31633d4c2ae 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Char.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Char.cs @@ -27,5 +27,16 @@ public static IEnumerable Char_ChangeCase_MemberData() [Benchmark] [ArgumentsSource(nameof(Char_ChangeCase_MemberData))] public char Char_ToUpper(char c, CultureInfo cultureName)=> char.ToUpper(c, cultureName); + + [Benchmark] + [ArgumentsSource(nameof(GetUnicodeCategoryArguments))] + public UnicodeCategory GetUnicodeCategory(char c) => char.GetUnicodeCategory(c); + + public static IEnumerable GetUnicodeCategoryArguments() + { + yield return new object[] { '.' }; + yield return new object[] { 'a' }; + yield return new object[] { '\x05D0' }; + } } } diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.DateTime.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.DateTime.cs index 0bdc7bf5cb9..94b398f56f0 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.DateTime.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.DateTime.cs @@ -35,5 +35,11 @@ public static IEnumerable ToString_MemberData() [Benchmark] public TimeSpan op_Subtraction() => date1 - date2; + + [Benchmark] + public DateTime ParseR() => DateTime.ParseExact("Mon, 03 Jun 1996 22:15:00 GMT", "r", null); + + [Benchmark] + public DateTime ParseO() => DateTime.ParseExact("1996-06-03T22:15:00.0000000", "o", null); } } diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Decimal.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Decimal.cs index c09c6048641..db7eea4841d 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Decimal.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Decimal.cs @@ -31,5 +31,29 @@ public static IEnumerable StringValues [Benchmark] [ArgumentsSource(nameof(StringValues))] public bool TryParse(string value) => decimal.TryParse(value, out _); + + private decimal _a = 67891.2345m; + private decimal _b = 12345.6789m; + + [Benchmark] + public decimal Add() => _a + _b; + + [Benchmark] + public decimal Subtract() => _a - _b; + + [Benchmark] + public decimal Multiply() => _a * _b; + + [Benchmark] + public decimal Divide() => _a / _b; + + [Benchmark] + public decimal Mod() => _a % _b; + + [Benchmark] + public decimal Floor() => decimal.Floor(_a); + + [Benchmark] + public decimal Round() => decimal.Round(_a); } } \ No newline at end of file diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Enum.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Enum.cs index 15c71440b8e..408f9c6527e 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Enum.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Enum.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using BenchmarkDotNet.Attributes; using MicroBenchmarks; @@ -20,6 +21,16 @@ public enum Colors Blue = 0x10 } + public enum ByteEnum : byte + { + A, + B + } + + [Benchmark] + [Arguments(Colors.Yellow)] + public string EnumToString(Colors value) => value.ToString(); + [Benchmark] [Arguments("Red")] [Arguments("Red, Orange, Yellow, Green, Blue")] @@ -34,5 +45,10 @@ public enum Colors [Benchmark] public bool HasFlag() => _greenAndRed.HasFlag(Colors.Green); + + private ByteEnum _byteEnum = ByteEnum.A; + + [Benchmark] + public void Compare() => Comparer.Default.Compare(_byteEnum, _byteEnum); } } diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs index e2123a4bb9d..074032e0419 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs @@ -11,11 +11,31 @@ namespace System.Tests public class Perf_Guid { const string guidStr = "a8a110d5-fc49-43c5-bf46-802db8f843ff"; + private readonly Guid _guid = new Guid(guidStr); + private readonly byte[] _buffer = new byte[16]; [Benchmark] public Guid NewGuid() => Guid.NewGuid(); [Benchmark] public Guid ctor_str() => new Guid(guidStr); + + [Benchmark] + public Guid Parse() => Guid.Parse(guidStr); + + [Benchmark] + public Guid ParseExactD() => Guid.ParseExact(guidStr, "D"); + + [Benchmark] + public string GuidToString() => _guid.ToString(); + +#if !NETFRAMEWORK + [Benchmark] + public Guid ToFromBytes() + { + _guid.TryWriteBytes(_buffer); + return new Guid(_buffer); + } +#endif } } \ No newline at end of file diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Int32.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Int32.cs index b0cb814d516..8c13a02dce4 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Int32.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Int32.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System.Collections.Generic; +using System.Globalization; using System.Linq; using BenchmarkDotNet.Attributes; using MicroBenchmarks; @@ -17,27 +18,37 @@ public class Perf_Int32 public static IEnumerable Values => new object[] { int.MinValue, + 4, // single digit (int)12345, // same value used by other tests to compare the perf int.MaxValue }; - public static IEnumerable StringValues => Values.Select(value => value.ToString()).ToArray(); + public static IEnumerable StringValuesDecimal => Values.Select(value => value.ToString()).ToArray(); + public static IEnumerable StringValuesHex => Values.Select(value => ((int)value).ToString("X")).ToArray(); [Benchmark] [ArgumentsSource(nameof(Values))] public string ToString(int value) => value.ToString(); [Benchmark] - [ArgumentsSource(nameof(StringValues))] + [ArgumentsSource(nameof(Values))] + public string ToStringHex(int value) => value.ToString("X"); + + [Benchmark] + [ArgumentsSource(nameof(StringValuesDecimal))] public int Parse(string value) => int.Parse(value); [Benchmark] - [ArgumentsSource(nameof(StringValues))] + [ArgumentsSource(nameof(StringValuesHex))] + public int ParseHex(string value) => int.Parse(value, NumberStyles.HexNumber); + + [Benchmark] + [ArgumentsSource(nameof(StringValuesDecimal))] public bool TryParse(string value) => int.TryParse(value, out _); #if !NETFRAMEWORK // API added in .NET Core 2.1 [Benchmark] - [ArgumentsSource(nameof(StringValues))] + [ArgumentsSource(nameof(StringValuesDecimal))] public int ParseSpan(string value) => int.Parse(value.AsSpan()); [Benchmark] @@ -45,7 +56,7 @@ public class Perf_Int32 public bool TryFormat(int value) => value.TryFormat(new Span(_destination), out _); [Benchmark] - [ArgumentsSource(nameof(StringValues))] + [ArgumentsSource(nameof(StringValuesDecimal))] public bool TryParseSpan(string value) => int.TryParse(value.AsSpan(), out _); #endif } diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.String.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.String.cs index 824c9c416cb..639d80e540f 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.String.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.String.cs @@ -61,6 +61,13 @@ public bool StartsWith(StringArguments size) [Arguments("dzsdzsDDZSDZSDZSddsz")] public int GetHashCode(string s) => s.GetHashCode(); + + [Benchmark] + [Arguments("")] + [Arguments("TeSt!")] + [Arguments("dzsdzsDDZSDZSDZSddsz")] + public int GetHashCodeOrdinalIgnoreCase(string s) + => StringComparer.OrdinalIgnoreCase.GetHashCode(s); [Benchmark] [Arguments("Test", 2, " Test")] @@ -234,6 +241,11 @@ public bool Equality(string s1, string s2) public bool Equals(string s1, string s2) => s1.Equals(s2); + [Benchmark] + [Arguments("dzsdzsDDZSDZSDZSddsz", "dzsdzsDDZSDZSDZSddsz")] + public bool EqualsIgnoreCase(string s1, string s2) + => s1.Equals(s2, StringComparison.OrdinalIgnoreCase); + [Benchmark] [Arguments("Testing {0}, {0:C}, {0:D5}, {0:E} - {0:F4}{0:G}{0:N} {0:X} !!", 8)] [Arguments("Testing {0}, {0:C}, {0:E} - {0:F4}{0:G}{0:N} , !!", 3.14159)] @@ -253,6 +265,7 @@ public string Interpolation_MultipleArgs(char c, string s) [Arguments("TeSt")] [Arguments("TEST")] [Arguments("test")] + [Arguments("This is a much longer piece of text that might benefit more from vectorization.")] public string ToUpper(string s) => s.ToUpper(); @@ -260,6 +273,7 @@ public string ToUpper(string s) [Arguments("TeSt")] [Arguments("TEST")] [Arguments("test")] + [Arguments("This is a much longer piece of text that might benefit more from vectorization.")] public string ToUpperInvariant(string s) => s.ToUpperInvariant(); @@ -267,6 +281,7 @@ public string ToUpperInvariant(string s) [Arguments("TeSt")] [Arguments("TEST")] [Arguments("test")] + [Arguments("This is a much longer piece of text that might benefit more from vectorization.")] public string ToLower(string s) => s.ToLower(); @@ -274,6 +289,7 @@ public string ToLower(string s) [Arguments("TeSt")] [Arguments("TEST")] [Arguments("test")] + [Arguments("This is a much longer piece of text that might benefit more from vectorization.")] public string ToLowerInvariant(string s) => s.ToLowerInvariant(); diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Uri.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Uri.cs index 02ca17d7f2e..ca7baa8da3c 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Uri.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Uri.cs @@ -12,5 +12,8 @@ public class Perf_Uri { [Benchmark] public string ParseAbsoluteUri() => new Uri("http://127.0.0.1:80").AbsoluteUri; + + [Benchmark] + public string DnsSafeHost() => new Uri("http://[fe80::3]%1").DnsSafeHost; } } diff --git a/src/benchmarks/micro/corefx/System.Security.Cryptography.X509Certificates/X509Certificate2Tests.cs b/src/benchmarks/micro/corefx/System.Security.Cryptography.X509Certificates/X509Certificate2Tests.cs new file mode 100644 index 00000000000..2299d64c0c9 --- /dev/null +++ b/src/benchmarks/micro/corefx/System.Security.Cryptography.X509Certificates/X509Certificate2Tests.cs @@ -0,0 +1,34 @@ +// 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 System.Net.Security; +using System.Net.Sockets; +using System.Security.Authentication; +using BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace System.Security.Cryptography.X509Certificates.Tests +{ + [BenchmarkCategory(Categories.CoreFX)] + public class X509Certificate2Tests + { + private readonly X509Certificate2 _cert = GetMicrosoftComCert(); + + private static X509Certificate2 GetMicrosoftComCert() + { + using (var client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) + { + client.Connect("microsoft.com", 443); + using (var ssl = new SslStream(new NetworkStream(client))) + { + ssl.AuthenticateAsClient("microsoft.com", null, SslProtocols.None, false); + return new X509Certificate2(ssl.RemoteCertificate); + } + } + } + + [Benchmark] + public string CertProp() => _cert.Thumbprint; + } +} diff --git a/src/benchmarks/micro/corefx/System.Threading.Tasks/Perf.AsyncMethods.cs b/src/benchmarks/micro/corefx/System.Threading.Tasks/Perf.AsyncMethods.cs index 561da0392fd..b727c80a4ef 100644 --- a/src/benchmarks/micro/corefx/System.Threading.Tasks/Perf.AsyncMethods.cs +++ b/src/benchmarks/micro/corefx/System.Threading.Tasks/Perf.AsyncMethods.cs @@ -33,5 +33,14 @@ public async Task SingleYieldMethodInvocation() async Task Yield() => await Task.Yield(); } + + [Benchmark(OperationsPerInvoke = 1_000_000)] + public async Task Yield() + { + for (int i = 0; i < 1_000_000; i++) + { + await Task.Yield(); + } + } } } diff --git a/src/benchmarks/micro/corefx/System.Threading.Timers/Perf.Timer.cs b/src/benchmarks/micro/corefx/System.Threading.Timers/Perf.Timer.cs index d60f6927e20..dbf8cdccc3e 100644 --- a/src/benchmarks/micro/corefx/System.Threading.Timers/Perf.Timer.cs +++ b/src/benchmarks/micro/corefx/System.Threading.Timers/Perf.Timer.cs @@ -72,5 +72,31 @@ public void AsynchronousContention() } Task.WaitAll(tasks); } + + [GlobalSetup(Target = nameof(ShortScheduleAndDisposeWithFiringTimers))] + public void SetupShortScheduleAndDisposeWithFiringTimers() + { + for (int i = 0; i < _timers.Length; i++) + { + _timers[i] = new Timer(_ => { }, null, i, i); + } + Thread.Sleep(1000); + } + + [GlobalCleanup(Target = nameof(ShortScheduleAndDisposeWithFiringTimers))] + public void CleanupShortScheduleAndDisposeWithFiringTimers() + { + using (var are = new AutoResetEvent(false)) + { + foreach (Timer t in _timers) + { + t.Dispose(are); + are.WaitOne(); + } + } + } + + [Benchmark] + public void ShortScheduleAndDisposeWithFiringTimers() => new Timer(_ => { }, 0, 100, 100).Dispose(); } } diff --git a/src/benchmarks/micro/corefx/System.Threading/Perf.CancellationToken.cs b/src/benchmarks/micro/corefx/System.Threading/Perf.CancellationToken.cs index 082825ebcb8..70e310bdf05 100644 --- a/src/benchmarks/micro/corefx/System.Threading/Perf.CancellationToken.cs +++ b/src/benchmarks/micro/corefx/System.Threading/Perf.CancellationToken.cs @@ -43,5 +43,14 @@ public void CreateLinkedTokenSource2() => [Benchmark] public void CreateLinkedTokenSource3() => CancellationTokenSource.CreateLinkedTokenSource(_tokens).Dispose(); + + [Benchmark] + public void CancelAfter() + { + using (var cts = new CancellationTokenSource()) + { + cts.CancelAfter(int.MaxValue - 1); + } + } } } diff --git a/src/benchmarks/micro/corefx/System.Threading/Perf.Thread.cs b/src/benchmarks/micro/corefx/System.Threading/Perf.Thread.cs new file mode 100644 index 00000000000..06ace285719 --- /dev/null +++ b/src/benchmarks/micro/corefx/System.Threading/Perf.Thread.cs @@ -0,0 +1,16 @@ +// 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 BenchmarkDotNet.Attributes; +using MicroBenchmarks; + +namespace System.Threading.Tests +{ + [BenchmarkCategory(Categories.CoreFX)] + public class Perf_Thread + { + [Benchmark] + public Thread CurrentThread() => Thread.CurrentThread; + } +} \ No newline at end of file From d287b0d1ab62613a32634ea3dd44b9381a2adde0 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 11:53:49 +0200 Subject: [PATCH 2/7] revert the renames that would change benchmark ID --- .../Perf.SocketsHttpHandler.cs | 23 ++++++++----------- .../Perf.WebUtility.cs | 4 ++-- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs b/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs index 08f69329e2f..281f1d1401d 100644 --- a/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs +++ b/src/benchmarks/micro/corefx/System.Net.Http/Perf.SocketsHttpHandler.cs @@ -20,14 +20,9 @@ namespace System.Net.Http.Tests public class SocketsHttpHandlerPerfTest { // the field names start with lowercase to keep to benchmark ID! do not change it - [Params(false, true)] - public bool Ssl { get; set; } - - [Params(false, true)] - public bool ChunkedResponse { get; set; } - - [Params(1, 1024, 10 * 1024 * 1024)] - public int ResponseLength { get; set; } + [Params(false, true)] public bool ssl; + [Params(false, true)] public bool chunkedResponse; + [Params(1, 100_000)] public int responseLength; private System.Security.Cryptography.X509Certificates.X509Certificate2 _serverCert; private Socket _listener; @@ -45,9 +40,9 @@ public void Setup() _listener.Bind(new IPEndPoint(IPAddress.Loopback, 0)); _listener.Listen(int.MaxValue); string responseText = - "HTTP/1.1 200 OK\r\n" + (ChunkedResponse ? - $"Transfer-Encoding: chunked\r\n\r\n{ResponseLength.ToString("X")}\r\n{new string('a', ResponseLength)}\r\n0\r\n\r\n" : - $"Content-Length: {ResponseLength}\r\n\r\n{new string('a', ResponseLength)}"); + "HTTP/1.1 200 OK\r\n" + (chunkedResponse ? + $"Transfer-Encoding: chunked\r\n\r\n{responseLength.ToString("X")}\r\n{new string('a', responseLength)}\r\n0\r\n\r\n" : + $"Content-Length: {responseLength}\r\n\r\n{new string('a', responseLength)}"); ReadOnlyMemory responseBytes = Encoding.UTF8.GetBytes(responseText); _serverTask = Task.Run(async () => @@ -61,7 +56,7 @@ public void Setup() try { Stream stream = new NetworkStream(s); - if (Ssl) + if (ssl) { var sslStream = new SslStream(stream, false, delegate { return true; }); await sslStream.AuthenticateAsServerAsync(_serverCert, false, SslProtocols.None, false); @@ -85,11 +80,11 @@ public void Setup() }); var ep = (IPEndPoint)_listener.LocalEndPoint; - var uri = new Uri($"http{(Ssl ? "s" : "")}://{ep.Address}:{ep.Port}/"); + var uri = new Uri($"http{(ssl ? "s" : "")}://{ep.Address}:{ep.Port}/"); _handler = new SocketsHttpHandler(); _invoker = new HttpMessageInvoker(_handler); - if (Ssl) + if (ssl) { _handler.SslOptions.RemoteCertificateValidationCallback = delegate { return true; }; } diff --git a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs index 1d3485ee238..05357dbab37 100644 --- a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs +++ b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.WebUtility.cs @@ -11,10 +11,10 @@ namespace System.Net.Tests public class Perf_WebUtility { [Benchmark] - public string UrlDecode_DecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxy%22"); + public string Decode_DecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxy%22"); [Benchmark] - public string UrlDecode_NoDecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxyz"); + public string Decode_NoDecodingRequired() => WebUtility.UrlDecode("abcdefghijklmnopqrstuvwxyz"); [Benchmark] public void HtmlDecode_Entities() => WebUtility.HtmlDecode("水水水水水水水"); From 88402199935567e1a9375de3215b17a069dcb319 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 12:05:20 +0200 Subject: [PATCH 3/7] split ToFromBytes to two separate benchmarks that measure 1 thing --- .../micro/corefx/System.Runtime/Perf.Guid.cs | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs b/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs index 2ac68d8af5a..108ec9a36db 100644 --- a/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs +++ b/src/benchmarks/micro/corefx/System.Runtime/Perf.Guid.cs @@ -11,10 +11,17 @@ namespace System.Tests public class Perf_Guid { const string guidStr = "a8a110d5-fc49-43c5-bf46-802db8f843ff"; - private readonly byte[] _buffer = new byte[16]; + + private readonly Guid _guid; + private readonly Guid _same; + private readonly byte[] _buffer; - private readonly Guid _guid = new Guid(guidStr); - private readonly Guid _same = new Guid(guidStr); + public Perf_Guid() + { + _guid = new Guid(guidStr); + _same = new Guid(guidStr); + _buffer = _guid.ToByteArray(); + } [Benchmark] public Guid NewGuid() => Guid.NewGuid(); @@ -22,6 +29,9 @@ public class Perf_Guid [Benchmark] public Guid ctor_str() => new Guid(guidStr); + [Benchmark] + public Guid ctor_bytes() => new Guid(_buffer); + [Benchmark] public bool EqualsSame() => _guid.Equals(_same); @@ -36,11 +46,7 @@ public class Perf_Guid #if !NETFRAMEWORK [Benchmark] - public Guid ToFromBytes() - { - _guid.TryWriteBytes(_buffer); - return new Guid(_buffer); - } + public bool TryWriteBytes() => _guid.TryWriteBytes(_buffer); #endif } } \ No newline at end of file From ff7c06135c8bc18632e32d2481df03f94a27ea14 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 12:09:09 +0200 Subject: [PATCH 4/7] fix the TrimArguments (IEnumerable => IEnumerable) --- .../micro/corefx/System.Memory/ReadOnlySpan.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs b/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs index defb43098b2..c73828b8c2d 100644 --- a/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs +++ b/src/benchmarks/micro/corefx/System.Memory/ReadOnlySpan.cs @@ -78,12 +78,12 @@ public int IndexOfString(string input, string value, StringComparison comparison [ArgumentsSource(nameof(TrimArguments))] public ReadOnlySpan Trim(string input) => input.AsSpan().Trim(); - public static IEnumerable TrimArguments => new List + public static IEnumerable TrimArguments() { - new object[] { "" }, - new object[] { " abcdefg " }, - new object[] { "abcdefg" } - }; + yield return ""; + yield return " abcdefg "; + yield return "abcdefg"; + } private static string GenerateInputString(char source, int count, char replaceChar, int replacePos) { From 2134834f1b6b35fcca5518c6b2e1a519b306f4e6 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 12:12:34 +0200 Subject: [PATCH 5/7] revert StreamWriter changes --- .../System.Runtime.Extensions/Perf.StreamWriter.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs index c32cefbbbb9..93944605478 100644 --- a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs +++ b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs @@ -19,6 +19,7 @@ public class Perf_StreamWriter private string _string2 = new string('a', 2), _string100 = new string('a', 100); private char[] _buffer2 = new string('a', 2).ToCharArray(), _buffer100 = new string('a', 100).ToCharArray(); private char[] _buffer12 = new string('a', 12).ToCharArray(), _buffer110 = new string('a', 110).ToCharArray(); + private MemoryStream _memoryStream; private StreamWriter _streamWriter; public IEnumerable WriteLengthMemberData() @@ -30,12 +31,14 @@ public IEnumerable WriteLengthMemberData() [GlobalSetup] public void Setup() { - _streamWriter = new StreamWriter(Stream.Null, new UTF8Encoding(false, true), DefaultStreamWriterBufferSize, leaveOpen: true); + _memoryStream = new MemoryStream(MemoryStreamSize); + _streamWriter = new StreamWriter(_memoryStream, new UTF8Encoding(false, true), DefaultStreamWriterBufferSize, leaveOpen: true); } [GlobalCleanup] public void Cleanup() { + _memoryStream.Dispose(); _streamWriter.Dispose(); } @@ -48,6 +51,7 @@ public void WriteCharArray(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; + var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -56,6 +60,7 @@ public void WriteCharArray(int writeLength) writer.Write(buffer); } writer.Flush(); + stream.Position = 0; } } @@ -68,6 +73,7 @@ public void WritePartialCharArray(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; + var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -76,6 +82,7 @@ public void WritePartialCharArray(int writeLength) writer.Write(buffer, 10, writeLength); } writer.Flush(); + stream.Position = 0; } } @@ -88,6 +95,7 @@ public void WriteString(int writeLength) int outerIteration = TotalWriteCount / innerIterations; var writer = _streamWriter; + var stream = _memoryStream; for (int i = 0; i < outerIteration; i++) { @@ -96,6 +104,7 @@ public void WriteString(int writeLength) writer.Write(value); } writer.Flush(); + stream.Position = 0; } } From 7c03aa4aa233ada23b4f32b74f807a09b73bca99 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 12:12:41 +0200 Subject: [PATCH 6/7] fix StreamWriter --- .../corefx/System.Runtime.Extensions/Perf.StreamWriter.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs index 93944605478..d0718e2e411 100644 --- a/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs +++ b/src/benchmarks/micro/corefx/System.Runtime.Extensions/Perf.StreamWriter.cs @@ -109,6 +109,10 @@ public void WriteString(int writeLength) } [Benchmark] - public void WriteFormat() => _streamWriter.Write("Writing out a value: {0}", 42); + public void WriteFormat() + { + _memoryStream.Position = 0; + _streamWriter.Write("Writing out a value: {0}", 42); + } } } From 40e3d78667df1651c6d4161d2b468de4a9722302 Mon Sep 17 00:00:00 2001 From: Adam Sitnik Date: Thu, 18 Jul 2019 12:15:13 +0200 Subject: [PATCH 7/7] bring back EmptyTakeSelectToArray which I've accidentaly removed when solving merge conflict --- src/benchmarks/micro/corefx/System.Linq/Perf.Enumerable.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/benchmarks/micro/corefx/System.Linq/Perf.Enumerable.cs b/src/benchmarks/micro/corefx/System.Linq/Perf.Enumerable.cs index c56d3a5264c..4db420d1b29 100644 --- a/src/benchmarks/micro/corefx/System.Linq/Perf.Enumerable.cs +++ b/src/benchmarks/micro/corefx/System.Linq/Perf.Enumerable.cs @@ -394,6 +394,9 @@ public IEnumerable ElementAtArguments() [ArgumentsSource(nameof(IEnumerableArgument))] public void Except(LinqTestData input) => input.Collection.Except(input.Collection).Consume(_consumer); + [Benchmark] + public void EmptyTakeSelectToArray() => Enumerable.Empty().Take(10).Select(i => i).ToArray(); + #if NETCOREAPP3_0 // API Available in .NET Core 3.0+ // Append() has two execution paths: AppendPrependIterator (a result of another Append or Prepend) and IEnumerable, this benchmark tests both // https://github.com/dotnet/corefx/blob/dcf1c8f51bcdbd79e08cc672e327d50612690a25/src/System.Linq/src/System/Linq/AppendPrepend.cs