diff --git a/.gitattributes b/.gitattributes index 519ecbb0374d..27e670318539 100644 --- a/.gitattributes +++ b/.gitattributes @@ -69,8 +69,10 @@ src/pal/tests/palsuite/paltestlist_to_be_reviewed.txt text eol=lf tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25.txt text eol=lf tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25000.txt text eol=lf -tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25.txt text eol=lf -tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25000.txt text eol=lf +tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25.txt text eol=lf +tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25000.txt text eol=lf +tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25.txt text eol=lf +tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25000.txt text eol=lf tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input.txt text eol=lf tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/knucleotide-input-big.txt text eol=lf diff --git a/tests/issues.targets b/tests/issues.targets index df8fc554d866..08dbf459e35a 100644 --- a/tests/issues.targets +++ b/tests/issues.targets @@ -393,13 +393,22 @@ needs triage - + 9314 - + 9314 - + + 9314 + + + 9314 + + + 9314 + + 9314 diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT index b95d43c36157..beec4d959b2c 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/README.TXT @@ -5,9 +5,13 @@ The benchmarks in these sub-directories are based on See the adjoining LICENSE.TXT file for license terms. -Our intention with these tests is to provide interesting test cases -for jit developers to use in daily development practice -- not to -produce variants that give the maximum possible performance. +Our intention with these tests is twofold: + 1 - To track .NET Core's performance on these benchmarks in the + same benchmarking system used for other internal .NET Core + performance benchmarks. + 2 - To make these available for daily JIT (and runtime) development, + as a factor in assessing the performance impact of compiler + (and runtime) changes. The benchmarks have been modified to fit into the CoreCLR test and performance test framework, as follows: @@ -19,19 +23,15 @@ performance test framework, as follows: xunit-performance iteration is approximately 1 second on modern x64 hardware - reducing verbosity when run as a benchmark - - reformatting (via the codeformatter tool) + - calling different APIs in a few places to allow compiling against + netstandard1.4 + - reformatting + - in the case of pidigits, implementing on top of .NET's BigInteger + type rather than p/invokes to the native GMP library These benchmarks are just a subset of the benchmarks available in C# from -the Benchmarks Game site. We've selected variants that do not rely on -multiple threads to ensure relative benchmark stability across a -variety of machines. - -We've excluded two benchmarks that are inherently multitheaded: -chamenosredux and threadring. We may revisit this as we improve our -ability to harness threading tests in a stable way. - -We've also excluded benchmarks that read in large input files: -knucleotide, regexdna, revcomp. - - - +the Benchmarks Game site. The highest-scoring C# .NET Core variant of each +benchmark is included, and in the (common) case of benchmarks where the +best-scoring variant uses multiple threads, we've also selected variants +that do not rely on multiple threads, to ensure relative benchmark stability +across a variety of machines. diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.cs new file mode 100644 index 000000000000..bf0b307721d1 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.cs @@ -0,0 +1,122 @@ +// 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. + +// Adapted from binary-trees C# .NET Core #2 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=csharpcore&id=2 +// aka (as of 2017-09-01) rev 1.3 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/binarytrees/binarytrees.csharp-2.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Marek Safar + *reset* +*/ + +using System; +using Microsoft.Xunit.Performance; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureGCCounts] + +namespace BenchmarksGame +{ + public class BinaryTrees_2 + { + const int minDepth = 4; + + public static int Main(String[] args) + { + int n = 0; + if (args.Length > 0) n = Int32.Parse(args[0]); + + int check = Bench(n, true); + int expected = 4398; + + // Return 100 on success, anything else on failure. + return check - expected + 100; + } + + [Benchmark(InnerIterationCount = 7)] + public static void RunBench() + { + Benchmark.Iterate(() => Bench(16, false)); + } + + static int Bench(int n, bool verbose) + { + int maxDepth = Math.Max(minDepth + 2, n); + int stretchDepth = maxDepth + 1; + + int check = (TreeNode.bottomUpTree(stretchDepth)).itemCheck(); + int checkSum = check; + if (verbose) Console.WriteLine("stretch tree of depth {0}\t check: {1}", stretchDepth, check); + + TreeNode longLivedTree = TreeNode.bottomUpTree(maxDepth); + + for (int depth = minDepth; depth <= maxDepth; depth += 2) + { + int iterations = 1 << (maxDepth - depth + minDepth); + + check = 0; + for (int i = 1; i <= iterations; i++) + { + check += (TreeNode.bottomUpTree(depth)).itemCheck(); + } + checkSum += check; + + if (verbose) + Console.WriteLine("{0}\t trees of depth {1}\t check: {2}", iterations, depth, check); + } + + check = longLivedTree.itemCheck(); + checkSum += check; + + if (verbose) + Console.WriteLine("long lived tree of depth {0}\t check: {1}", maxDepth, check); + + return checkSum; + } + + + struct TreeNode + { + class Next + { + public TreeNode left, right; + } + + private Next next; + + internal static TreeNode bottomUpTree(int depth) + { + if (depth > 0) + { + return new TreeNode( + bottomUpTree(depth - 1) + , bottomUpTree(depth - 1) + ); + } + else + { + return new TreeNode(); + } + } + + TreeNode(TreeNode left, TreeNode right) + { + this.next = new Next(); + this.next.left = left; + this.next.right = right; + } + + internal int itemCheck() + { + // if necessary deallocate here + if (next == null) return 1; + else return 1 + next.left.itemCheck() + next.right.itemCheck(); + } + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.csproj similarity index 95% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.csproj index d10772f2af2c..e032f83eb6c1 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-2.csproj @@ -1,4 +1,4 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.cs new file mode 100644 index 000000000000..6b4e092b0e26 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.cs @@ -0,0 +1,147 @@ +// 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. + +// Adapted from binary-trees C# .NET Core #5 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=binarytrees&lang=csharpcore&id=5 +// aka (as of 2017-09-01) rev 1.1 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/binarytrees/binarytrees.csharp-5.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Marek Safar + *reset* + concurrency added by Peperud + minor improvements by Alex Yakunin +*/ + +using System; +using System.Runtime.CompilerServices; +using System.Threading.Tasks; +using Microsoft.Xunit.Performance; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureGCCounts] + +namespace BenchmarksGame +{ + public sealed class BinaryTrees_5 + { + public const int MinDepth = 4; + + public static int Main(string[] args) + { + var n = args.Length == 0 ? 0 : int.Parse(args[0]); + + int check = Bench(n, true); + int expected = 4398; + + // Return 100 on success, anything else on failure. + return check - expected + 100; + } + + [Benchmark(InnerIterationCount = 7)] + public static void RunBench() + { + Benchmark.Iterate(() => Bench(16, false)); + } + + static int Bench(int n, bool verbose) + { + var maxDepth = n < (MinDepth + 2) ? MinDepth + 2 : n; + var stretchDepth = maxDepth + 1; + + var stretchDepthTask = Task.Run(() => TreeNode.CreateTree(stretchDepth).CountNodes()); + var maxDepthTask = Task.Run(() => TreeNode.CreateTree(maxDepth).CountNodes()); + + var tasks = new Task[(maxDepth - MinDepth) / 2 + 1]; + for (int depth = MinDepth, ti = 0; depth <= maxDepth; depth += 2, ti++) + { + var iterationCount = 1 << (maxDepth - depth + MinDepth); + var depthCopy = depth; // To make sure closure value doesn't change + tasks[ti] = Task.Run(() => + { + var count = 0; + if (depthCopy >= 17) + { + // Parallelized computation for relatively large tasks + var miniTasks = new Task[iterationCount]; + for (var i = 0; i < iterationCount; i++) + miniTasks[i] = Task.Run(() => TreeNode.CreateTree(depthCopy).CountNodes()); + Task.WaitAll(miniTasks); + for (var i = 0; i < iterationCount; i++) + count += miniTasks[i].Result; + } + else + { + // Sequential computation for smaller tasks + for (var i = 0; i < iterationCount; i++) + count += TreeNode.CreateTree(depthCopy).CountNodes(); + } + return $"{iterationCount}\t trees of depth {depthCopy}\t check: {count}"; + }); + } + Task.WaitAll(tasks); + + if (verbose) + { + int count = 0; + Action printAndSum = (string s) => + { + Console.WriteLine(s); + count += int.Parse(s.Substring(s.LastIndexOf(':') + 1).TrimStart()); + }; + + printAndSum(String.Format("stretch tree of depth {0}\t check: {1}", + stretchDepth, stretchDepthTask.Result)); + foreach (var task in tasks) + printAndSum(task.Result); + printAndSum(String.Format("long lived tree of depth {0}\t check: {1}", + maxDepth, maxDepthTask.Result)); + + return count; + } + + return 0; + } + } + + public struct TreeNode + { + public sealed class NodeData + { + public TreeNode Left, Right; + + public NodeData(TreeNode left, TreeNode right) + { + Left = left; + Right = right; + } + } + + public NodeData Data; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public TreeNode(TreeNode left, TreeNode right) + { + Data = new NodeData(left, right); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static TreeNode CreateTree(int depth) + { + return depth <= 0 + ? default(TreeNode) + : new TreeNode(CreateTree(depth - 1), CreateTree(depth - 1)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public int CountNodes() + { + if (ReferenceEquals(Data, null)) + return 1; + return 1 + Data.Left.CountNodes() + Data.Right.CountNodes(); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees3.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.csproj similarity index 95% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees3.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.csproj index 3dffd5e4bf55..e032f83eb6c1 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees3.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-5.csproj @@ -1,4 +1,4 @@ - + @@ -31,7 +31,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs deleted file mode 100644 index 6e446294995f..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp.cs +++ /dev/null @@ -1,154 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Marek Safar - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.Runtime.CompilerServices; -using Xunit; - -[assembly: OptimizeForBenchmarks] -[assembly: MeasureGCCounts] - -namespace BenchmarksGame -{ -public class BinaryTrees -{ - private const int minDepth = 4; - private const int Iterations = 1; - - [MethodImpl(MethodImplOptions.NoInlining)] - private static bool Bench(bool verbose = false) - { - int n = 16; - int maxDepth = Math.Max(minDepth + 2, n); - int stretchDepth = maxDepth + 1; - int t = 0; - - int check = (TreeNode.bottomUpTree(0, stretchDepth)).itemCheck(); - if (verbose) - { - Console.WriteLine("stretch tree of depth {0}\t check: {1}", stretchDepth, check); - } - t += check; - - TreeNode longLivedTree = TreeNode.bottomUpTree(0, maxDepth); - - for (int depth = minDepth; depth <= maxDepth; depth += 2) - { - int iterations = 1 << (maxDepth - depth + minDepth); - - check = 0; - for (int i = 1; i <= iterations; i++) - { - check += (TreeNode.bottomUpTree(i, depth)).itemCheck(); - check += (TreeNode.bottomUpTree(-i, depth)).itemCheck(); - } - - if (verbose) - { - Console.WriteLine("{0}\t trees of depth {1}\t check: {2}", - iterations * 2, depth, check); - } - - t += check; - } - - if (verbose) - { - Console.WriteLine("long lived tree of depth {0}\t check: {1}", - maxDepth, longLivedTree.itemCheck()); - } - - t += check; - - return (t == -174785); - } - - private struct TreeNode - { - private class Next - { - public TreeNode left, right; - } - - private Next _next; - private int _item; - - private TreeNode(int item) - { - _item = item; - _next = null; - } - - internal static TreeNode bottomUpTree(int item, int depth) - { - if (depth > 0) - { - return new TreeNode( - bottomUpTree(2 * item - 1, depth - 1) - , bottomUpTree(2 * item, depth - 1) - , item - ); - } - else - { - return new TreeNode(item); - } - } - - private TreeNode(TreeNode left, TreeNode right, int item) - { - _next = new Next(); - _next.left = left; - _next.right = right; - _item = item; - } - - internal int itemCheck() - { - // if necessary deallocate here - if (_next == null) return _item; - else return _item + _next.left.itemCheck() - _next.right.itemCheck(); - } - } - - [Benchmark] - public static void Test() - { - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - Bench(); - } - } - } - } - - private static bool TestBase() - { - bool result = true; - for (int i = 0; i < Iterations; i++) - { - result &= Bench(true); - } - return result; - } - - public static int Main() - { - bool result = TestBase(); - return (result ? 100 : -1); - } -} -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp3.cs deleted file mode 100644 index 0cc239274be4..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees.csharp3.cs +++ /dev/null @@ -1,141 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - Based on code originally contributed by Marek Safar - and optimized by kasthack - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.Runtime.CompilerServices; -using Xunit; - -[assembly: OptimizeForBenchmarks] -[assembly: MeasureGCCounts] - -namespace BenchmarksGame -{ -public class BinaryTrees3 -{ - private const int minDepth = 4; - private const int Iterations = 1; - - [MethodImpl(MethodImplOptions.NoInlining)] - private static bool Bench(bool verbose = false) - { - int n = 16; - int maxDepth = Math.Max(minDepth + 2, n); - int stretchDepth = maxDepth + 1; - int t = 0; - - int check = (TreeNode.bottomUpTree(0, stretchDepth)).itemCheck(); - if (verbose) - { - Console.WriteLine("stretch tree of depth {0}\t check: {1}", stretchDepth, check); - } - t += check; - - TreeNode longLivedTree = TreeNode.bottomUpTree(0, maxDepth); - - for (int depth = minDepth; depth <= maxDepth; depth += 2) - { - int iterations = 1 << (maxDepth - depth + minDepth); - - check = 0; - for (int i = 1; i <= iterations; i++) - { - check += (TreeNode.bottomUpTree(i, depth)).itemCheck(); - check += (TreeNode.bottomUpTree(-i, depth)).itemCheck(); - } - - if (verbose) - { - Console.WriteLine("{0}\t trees of depth {1}\t check: {2}", - iterations * 2, depth, check); - } - - t += check; - } - - if (verbose) - { - Console.WriteLine("long lived tree of depth {0}\t check: {1}", - maxDepth, longLivedTree.itemCheck()); - } - - t += check; - - return (t == -174785); - } - - private class TreeNode - { - private TreeNode left, right; - private int item; - - private TreeNode(int item) - { - this.item = item; - } - - internal static TreeNode bottomUpTree(int item, int depth) - { - TreeNode t; - ChildTreeNodes(out t, item, depth - 1); - return t; - } - - static void ChildTreeNodes(out TreeNode node, int item, int depth) - { - node = new TreeNode(item); - if ( depth > 0 ) - { - ChildTreeNodes(out node.left, 2 * item - 1, depth - 1); - ChildTreeNodes(out node.right, 2 * item, depth - 1); - } - } - - internal int itemCheck() - { - if (right == null) return item; - else return item + left.itemCheck() - right.itemCheck(); - } - } - - [Benchmark] - public static void Test() - { - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - Bench(); - } - } - } - } - - private static bool TestBase() - { - bool result = true; - for (int i = 0; i < Iterations; i++) - { - result &= Bench(true); - } - return result; - } - - public static int Main() - { - bool result = TestBase(); - return (result ? 100 : -1); - } -} -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.cs new file mode 100644 index 000000000000..f7a8154ee78d --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.cs @@ -0,0 +1,102 @@ +// 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. + +// Adapted from fannkuch-redux C# .NET Core #2 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fannkuchredux&lang=csharpcore&id=2 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/fannkuchredux/fannkuchredux.csharp-2.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy, transliterated from Mike Pall's Lua program +*/ + +using System; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class FannkuchRedux_2 + { + public static int[] fannkuch(int n) + { + int[] p = new int[n], q = new int[n], s = new int[n]; + int sign = 1, maxflips = 0, sum = 0, m = n - 1; + for (int i = 0; i < n; i++) { p[i] = i; q[i] = i; s[i] = i; } + do + { + // Copy and flip. + var q0 = p[0]; // Cache 0th element. + if (q0 != 0) + { + for (int i = 1; i < n; i++) q[i] = p[i]; // Work on a copy. + var flips = 1; + do + { + var qq = q[q0]; + if (qq == 0) + { // ... until 0th element is 0. + sum += sign * flips; + if (flips > maxflips) maxflips = flips; // New maximum? + break; + } + q[q0] = q0; + if (q0 >= 3) + { + int i = 1, j = q0 - 1, t; + do { t = q[i]; q[i] = q[j]; q[j] = t; i++; j--; } while (i < j); + } + q0 = qq; flips++; + } while (true); + } + // Permute. + if (sign == 1) + { + var t = p[1]; p[1] = p[0]; p[0] = t; sign = -1; // Rotate 0<-1. + } + else + { + var t = p[1]; p[1] = p[2]; p[2] = t; sign = 1; // Rotate 0<-1 and 0<-1<-2. + for (int i = 2; i < n; i++) + { + var sx = s[i]; + if (sx != 0) { s[i] = sx - 1; break; } + if (i == m) return new int[] { sum, maxflips }; // Out of permutations. + s[i] = i; + // Rotate 0<-...<-i+1. + t = p[0]; for (int j = 0; j <= i; j++) { p[j] = p[j + 1]; } + p[i + 1] = t; + } + } + } while (true); + } + + static int Main(string[] args) + { + int n = (args.Length > 0) ? Int32.Parse(args[0]) : 7; + var pf = fannkuch(n); + Console.Write("{0}\nPfannkuchen({1}) = {2}\n", pf[0], n, pf[1]); + + int expected = 228; + + // Return 100 on success, anything else on failure. + return pf[0] - expected + 100; + } + + [Benchmark(InnerIterationCount = 7)] + [InlineData(10, 73196)] + public static void RunBench(int n, int expectedSum) + { + Benchmark.Iterate(() => + { + var pf = fannkuch(n); + Assert.Equal(expectedSum, pf[0]); + }); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.csproj similarity index 94% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.csproj index 30c542ee2777..56d2c065b93c 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-2.csproj @@ -5,7 +5,7 @@ Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {E4AA647E-10E6-40E1-BD01-3BA97AA204BC} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -28,7 +28,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.cs new file mode 100644 index 000000000000..562a62468fbb --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.cs @@ -0,0 +1,158 @@ +// 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. + +// Adapted from fannkuch-redux C# .NET Core #5 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fannkuchredux&lang=csharpcore&id=5 +// aka (as of 2017-09-01) rev 1.6 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/fannkuchredux/fannkuchredux.csharp-5.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy, transliterated from Oleg Mazurov's Java program + concurrency fix and minor improvements by Peperud + parallel and small optimisations by Anthony Lloyd +*/ + +using System; +using System.Threading; +using System.Runtime.CompilerServices; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public static class FannkuchRedux_5 + { + static int[] fact, chkSums, maxFlips; + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void firstPermutation(int[] p, int[] pp, int[] count, int idx) + { + for (int i = 0; i < p.Length; ++i) p[i] = i; + for (int i = count.Length - 1; i > 0; --i) + { + int d = idx / fact[i]; + count[i] = d; + if (d > 0) + { + idx = idx % fact[i]; + for (int j = i; j >= 0; --j) pp[j] = p[j]; + for (int j = 0; j <= i; ++j) p[j] = pp[(j + d) % (i + 1)]; + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int nextPermutation(int[] p, int[] count) + { + int first = p[1]; + p[1] = p[0]; + p[0] = first; + int i = 1; + while (++count[i] > i) + { + count[i++] = 0; + int next = p[1]; + p[0] = next; + for (int j = 1; j < i;) p[j] = p[++j]; + p[i] = first; + first = next; + } + return first; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static int countFlips(int first, int[] p, int[] pp) + { + if (first == 0) return 0; + if (p[first] == 0) return 1; + for (int i = 0; i < pp.Length; i++) pp[i] = p[i]; + int flips = 2; + while (true) + { + for (int lo = 1, hi = first - 1; lo < hi; lo++, hi--) + { + int t = pp[lo]; + pp[lo] = pp[hi]; + pp[hi] = t; + } + int tp = pp[first]; + if (pp[tp] == 0) return flips; + pp[first] = first; + first = tp; + flips++; + } + } + + static void run(int n, int taskId, int taskSize) + { + int[] p = new int[n], pp = new int[n], count = new int[n]; + firstPermutation(p, pp, count, taskId * taskSize); + int chksum = countFlips(p[0], p, pp); + int maxflips = chksum; + while (--taskSize > 0) + { + var flips = countFlips(nextPermutation(p, count), p, pp); + chksum += (1 - (taskSize % 2) * 2) * flips; + if (flips > maxflips) maxflips = flips; + } + chkSums[taskId] = chksum; + maxFlips[taskId] = maxflips; + } + + public static int Main(string[] args) + { + int n = args.Length > 0 ? int.Parse(args[0]) : 7; + int sum = Bench(n, true); + + int expected = 16; + + // Return 100 on success, anything else on failure. + return sum - expected + 100; + } + + [Benchmark(InnerIterationCount = 20)] + [InlineData(10, 38)] + public static void RunBench(int n, int expectedSum) + { + Benchmark.Iterate(() => + { + int sum = Bench(n, false); + Assert.Equal(expectedSum, sum); + }); + } + + static int Bench(int n, bool verbose) + { + fact = new int[n + 1]; + fact[0] = 1; + var factn = 1; + for (int i = 1; i < fact.Length; i++) { fact[i] = factn *= i; } + + int nTasks = Environment.ProcessorCount; + chkSums = new int[nTasks]; + maxFlips = new int[nTasks]; + int taskSize = factn / nTasks; + var threads = new Thread[nTasks]; + for (int i = 1; i < nTasks; i++) + { + int j = i; + (threads[j] = new Thread(() => run(n, j, taskSize))).Start(); + } + run(n, 0, taskSize); + int chksum = chkSums[0], maxflips = maxFlips[0]; + for (int i = 1; i < threads.Length; i++) + { + threads[i].Join(); + chksum += chkSums[i]; + if (maxFlips[i] > maxflips) maxflips = maxFlips[i]; + } + if (verbose) Console.Out.WriteLineAsync(chksum + "\nPfannkuchen(" + n + ") = " + maxflips); + + return maxflips; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.csproj similarity index 94% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.csproj index 003871e447fd..147e656df585 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-5.csproj @@ -5,7 +5,7 @@ Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {F49D82D3-9D13-47B5-83F8-52B1FE3FF452} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -28,7 +28,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.cs new file mode 100644 index 000000000000..0535c21adf44 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.cs @@ -0,0 +1,307 @@ +// 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. + +// Adapted from fasta C# .NET Core program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fasta&lang=csharpcore&id=1 +// aka (as of 2017-09-01) rev 1.1 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/fasta/fasta.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Serge Smith + further optimized (rewrote threading, random generation loop) by Jan de Vaan + modified by Josh Goldfoot (fasta-repeat buffering) +*/ + +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Xunit.Performance; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class Fasta_1 + { + const int LineLength = 60; + + const int IM = 139968; + const int IA = 3877; + const int IC = 29573; + static int seed = 42; + + public static int Main(string[] args) + { + int n = args.Length > 0 ? Int32.Parse(args[0]) : 1000; + + Bench(n, true); + return 100; + } + + [Benchmark(InnerIterationCount = 4000)] + public static void RunBench() + { + Benchmark.Iterate(() => Bench(5000, false)); + } + + static void Bench(int n, bool verbose) + { + MakeCumulative(IUB); + MakeCumulative(HomoSapiens); + + using (var s = (verbose ? Console.OpenStandardOutput() : Stream.Null)) + { + MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(ALU), n * 2, s); + MakeRandomFasta("TWO", "IUB ambiguity codes", IUB, n * 3, s); + MakeRandomFasta("THREE", "Homo sapiens frequency", HomoSapiens, n * 5, s); + } + } + + + + public static IEnumerable TransformQueue(BlockingCollection queue, + Func transform, int threadCount) + { + var tasks = new Task[threadCount]; + + for (int i = 0; i < threadCount; ++i) + { + T input; + if (!queue.TryTake(out input, Timeout.Infinite)) + break; + + tasks[i] = Task.Run(() => transform(input)); + } + + int pos = 0; + while (true) + { + if (tasks[pos] == null) + break; + + yield return tasks[pos].Result; + + T input; + tasks[pos] = queue.TryTake(out input, Timeout.Infinite) + ? Task.Run(() => transform(input)) + : null; + + pos = (pos + 1) % threadCount; + } + } + + + + static void MakeRandomFasta(string id, string desc, + Frequency[] a, int n, Stream s) + { + var queue = new BlockingCollection(2); + + var bufferCount = Environment.ProcessorCount + 4; + + Task.Run(() => + { + var len = LineLength * 40; + var buffers = Enumerable.Range(0, bufferCount) + .Select(i => new int[len]).ToArray(); + var index = 0; + for (var i = 0; i < n; i += len) + { + var buffer = n - i < len + ? new int[n - i] + : buffers[index++ % buffers.Length]; + + FillRandom(buffer); + queue.Add(buffer); + } + queue.CompleteAdding(); + }); + + byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); + s.Write(descStr, 0, descStr.Length); + + foreach (var r in TransformQueue(queue, + rnd => SelectNucleotides(a, rnd), Environment.ProcessorCount)) + { + s.Write(r, 0, r.Length); + } + + } + + private static byte[] SelectNucleotides(Frequency[] a, int[] rnd) + { + var resLength = (rnd.Length / LineLength) * (LineLength + 1); + if (rnd.Length % LineLength != 0) + { + resLength += rnd.Length % LineLength + 1; + } + + var buf = new byte[resLength]; + var index = 0; + for (var i = 0; i < rnd.Length; i += LineLength) + { + var len = Math.Min(LineLength, rnd.Length - i); + for (var j = 0; j < len; ++j) + buf[index++] = SelectRandom(a, (int)rnd[i + j]); + buf[index++] = (byte)'\n'; + } + return buf; + } + + static void MakeRepeatFasta(string id, string desc, + byte[] alu, int n, Stream s) + { + byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); + s.Write(descStr, 0, descStr.Length); + + /* JG: fasta_repeat repeats every len(alu) * line-length = 287 * 61 = 17507 characters. + So, calculate this once, then just print that buffer over and over. */ + + byte[] sequence; + int sequenceLength; + using (var unstandardOut = new MemoryStream(alu.Length * (LineLength + 1) + 1)) + { + MakeRepeatFastaBuffer(alu, alu.Length * LineLength, unstandardOut); + sequenceLength = (int)unstandardOut.Length; + sequence = new byte[sequenceLength]; + unstandardOut.Seek(0, SeekOrigin.Begin); + unstandardOut.Read(sequence, 0, sequenceLength); + } + int outputBytes = n + n / 60; + while (outputBytes >= sequenceLength) + { + s.Write(sequence, 0, sequenceLength); + outputBytes -= sequenceLength; + } + if (outputBytes > 0) + { + s.Write(sequence, 0, outputBytes); + s.WriteByte((byte)'\n'); + } + } + + static void MakeRepeatFastaBuffer(byte[] alu, int n, Stream s) + { + var index = 0; + int m = 0; + int k = 0; + int kn = alu.Length; + var buf = new byte[1024]; + + while (n > 0) + { + m = n < LineLength ? n : LineLength; + + if (buf.Length - index < m) + { + s.Write(buf, 0, index); + index = 0; + } + + for (int i = 0; i < m; i++) + { + if (k == kn) + k = 0; + + buf[index++] = alu[k]; + k++; + } + + buf[index++] = (byte)'\n'; + n -= LineLength; + } + + if (index != 0) + s.Write(buf, 0, index); + } + + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static byte SelectRandom(Frequency[] a, int r) + { + for (int i = 0; i < a.Length - 1; i++) + if (r < a[i].p) + return a[i].c; + + return a[a.Length - 1].c; + } + + static void MakeCumulative(Frequency[] a) + { + double cp = 0; + for (int i = 0; i < a.Length; i++) + { + cp += a[i].p; + a[i].p = cp; + } + } + + static string ALU = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + + struct Frequency + { + public readonly byte c; + public double p; + + public Frequency(char c, double p) + { + this.c = (byte)c; + this.p = (p * IM); + } + } + + static Frequency[] IUB = { + new Frequency ('a', 0.27), + new Frequency ('c', 0.12), + new Frequency ('g', 0.12), + new Frequency ('t', 0.27), + + new Frequency ('B', 0.02), + new Frequency ('D', 0.02), + new Frequency ('H', 0.02), + new Frequency ('K', 0.02), + new Frequency ('M', 0.02), + new Frequency ('N', 0.02), + new Frequency ('R', 0.02), + new Frequency ('S', 0.02), + new Frequency ('V', 0.02), + new Frequency ('W', 0.02), + new Frequency ('Y', 0.02) + }; + + static Frequency[] HomoSapiens = { + new Frequency ('a', 0.3029549426680), + new Frequency ('c', 0.1979883004921), + new Frequency ('g', 0.1975473066391), + new Frequency ('t', 0.3015094502008) + }; + + + private static void FillRandom(int[] result) + { + var s = seed; + for (var i = 0; i < result.Length; i++) + { + s = (s * IA + IC) % IM; + result[i] = s; + } + seed = s; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.csproj similarity index 94% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.csproj index be7e66e2a3ef..8deda2377e58 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-1.csproj @@ -5,7 +5,7 @@ Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {E85110FB-64D0-44E7-B040-1862B62A6EAC} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -28,7 +28,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.cs new file mode 100644 index 000000000000..3694e5de47fd --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.cs @@ -0,0 +1,210 @@ +// 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. + +// Adapted from fasta C# .NET Core #2 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=fasta&lang=csharpcore&id=2 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/fasta/fasta.csharp-2.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy + optimizations by Alp Toker +*/ + +using System; +using System.IO; +using System.Text; +using Microsoft.Xunit.Performance; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class Fasta_2 + { + static int Main(string[] args) + { + int n = args.Length > 0 ? Int32.Parse(args[0]) : 1000; + + Bench(n, true); + return 100; + } + + [Benchmark(InnerIterationCount = 2500)] + public static void RunBench() + { + Benchmark.Iterate(() => Bench(5000, false)); + } + + static void Bench(int n, bool verbose) + { + MakeCumulative(HomoSapiens); + MakeCumulative(IUB); + + using (Stream s = (verbose ? Console.OpenStandardOutput() : Stream.Null)) + { + MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(ALU), n * 2, s); + MakeRandomFasta("TWO", "IUB ambiguity codes", IUB, n * 3, s); + MakeRandomFasta("THREE", "Homo sapiens frequency", HomoSapiens, n * 5, s); + } + } + + // The usual pseudo-random number generator + + const int IM = 139968; + const int IA = 3877; + const int IC = 29573; + static int seed = 42; + + static double random(double max) + { + return max * ((seed = (seed * IA + IC) % IM) * (1.0 / IM)); + } + + // Weighted selection from alphabet + + static string ALU = + "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + + "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + + "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + + "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + + "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + + "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + + "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; + + class Frequency + { + public byte c; + public double p; + + public Frequency(char c, double p) + { + this.c = (byte)c; + this.p = p; + } + } + + static Frequency[] IUB = { + new Frequency ('a', 0.27), + new Frequency ('c', 0.12), + new Frequency ('g', 0.12), + new Frequency ('t', 0.27), + + new Frequency ('B', 0.02), + new Frequency ('D', 0.02), + new Frequency ('H', 0.02), + new Frequency ('K', 0.02), + new Frequency ('M', 0.02), + new Frequency ('N', 0.02), + new Frequency ('R', 0.02), + new Frequency ('S', 0.02), + new Frequency ('V', 0.02), + new Frequency ('W', 0.02), + new Frequency ('Y', 0.02) + }; + + static Frequency[] HomoSapiens = { + new Frequency ('a', 0.3029549426680), + new Frequency ('c', 0.1979883004921), + new Frequency ('g', 0.1975473066391), + new Frequency ('t', 0.3015094502008) + }; + + static void MakeCumulative(Frequency[] a) + { + double cp = 0.0; + for (int i = 0; i < a.Length; i++) + { + cp += a[i].p; + a[i].p = cp; + } + } + + // naive + static byte SelectRandom(Frequency[] a) + { + double r = random(1.0); + + for (int i = 0; i < a.Length; i++) + if (r < a[i].p) + return a[i].c; + + return a[a.Length - 1].c; + } + + const int LineLength = 60; + static int index = 0; + static byte[] buf = new byte[1024]; + + static void MakeRandomFasta(string id, string desc, Frequency[] a, int n, Stream s) + { + index = 0; + int m = 0; + + byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); + s.Write(descStr, 0, descStr.Length); + + while (n > 0) + { + m = n < LineLength ? n : LineLength; + + if (buf.Length - index < m) + { + s.Write(buf, 0, index); + index = 0; + } + + for (int i = 0; i < m; i++) + { + buf[index++] = SelectRandom(a); + } + + buf[index++] = (byte)'\n'; + n -= LineLength; + } + + if (index != 0) + s.Write(buf, 0, index); + } + + static void MakeRepeatFasta(string id, string desc, byte[] alu, int n, Stream s) + { + index = 0; + int m = 0; + int k = 0; + int kn = alu.Length; + + byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); + s.Write(descStr, 0, descStr.Length); + + while (n > 0) + { + m = n < LineLength ? n : LineLength; + + if (buf.Length - index < m) + { + s.Write(buf, 0, index); + index = 0; + } + + for (int i = 0; i < m; i++) + { + if (k == kn) + k = 0; + + buf[index++] = alu[k]; + k++; + } + + buf[index++] = (byte)'\n'; + n -= LineLength; + } + + if (index != 0) + s.Write(buf, 0, index); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.csproj new file mode 100644 index 000000000000..94e4bedd0e18 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-2.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {BC31B732-E7E4-4458-8D14-3DBF63A4A576} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs deleted file mode 100644 index 3e97d6442915..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csharp-2.cs +++ /dev/null @@ -1,222 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Isaac Gouy - optimizations by Alp Toker - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.IO; -using System.Text; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ -public class Fasta -{ -#if DEBUG - private const int Iterations = 1; -#else - const int Iterations = 800; -#endif - - public static int Main(string[] args) - { - MakeCumulative(s_homoSapiens); - MakeCumulative(s_IUB); - - int n = args.Length > 0 ? Int32.Parse(args[0]) : 1000; - - using (Stream s = Console.OpenStandardOutput()) - { - MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2, s); - MakeRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3, s); - MakeRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5, s); - } - return 100; - } - - [Benchmark] - public static void Bench() - { - int n = 5000; - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - using (Stream s = Stream.Null) - { - MakeRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2, s); - MakeRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3, s); - MakeRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5, s); - } - } - } - } - } - - // The usual pseudo-random number generator - - private const int IM = 139968; - private const int IA = 3877; - private const int IC = 29573; - private static int s_seed = 42; - - private static double random(double max) - { - return max * ((s_seed = (s_seed * IA + IC) % IM) * (1.0 / IM)); - } - - // Weighted selection from alphabet - - private static string s_ALU = - "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + - "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + - "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + - "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + - "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + - "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + - "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; - - private class Frequency - { - public byte c; - public double p; - - public Frequency(char c, double p) - { - this.c = (byte)c; - this.p = p; - } - } - - private static Frequency[] s_IUB = { - new Frequency ('a', 0.27) - ,new Frequency ('c', 0.12) - ,new Frequency ('g', 0.12) - ,new Frequency ('t', 0.27) - - ,new Frequency ('B', 0.02) - ,new Frequency ('D', 0.02) - ,new Frequency ('H', 0.02) - ,new Frequency ('K', 0.02) - ,new Frequency ('M', 0.02) - ,new Frequency ('N', 0.02) - ,new Frequency ('R', 0.02) - ,new Frequency ('S', 0.02) - ,new Frequency ('V', 0.02) - ,new Frequency ('W', 0.02) - ,new Frequency ('Y', 0.02) - }; - - private static Frequency[] s_homoSapiens = { - new Frequency ('a', 0.3029549426680) - ,new Frequency ('c', 0.1979883004921) - ,new Frequency ('g', 0.1975473066391) - ,new Frequency ('t', 0.3015094502008) - }; - - private static void MakeCumulative(Frequency[] a) - { - double cp = 0.0; - for (int i = 0; i < a.Length; i++) - { - cp += a[i].p; - a[i].p = cp; - } - } - - // naive - private static byte SelectRandom(Frequency[] a) - { - double r = random(1.0); - - for (int i = 0; i < a.Length; i++) - if (r < a[i].p) - return a[i].c; - - return a[a.Length - 1].c; - } - - private const int LineLength = 60; - private static int s_index = 0; - private static byte[] s_buf = new byte[1024]; - - private static void MakeRandomFasta(string id, string desc, Frequency[] a, int n, Stream s) - { - s_index = 0; - int m = 0; - - byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); - s.Write(descStr, 0, descStr.Length); - - while (n > 0) - { - m = n < LineLength ? n : LineLength; - - if (s_buf.Length - s_index < m) - { - s.Write(s_buf, 0, s_index); - s_index = 0; - } - - for (int i = 0; i < m; i++) - { - s_buf[s_index++] = SelectRandom(a); - } - - s_buf[s_index++] = (byte)'\n'; - n -= LineLength; - } - - if (s_index != 0) - s.Write(s_buf, 0, s_index); - } - - private static void MakeRepeatFasta(string id, string desc, byte[] alu, int n, Stream s) - { - s_index = 0; - int m = 0; - int k = 0; - int kn = alu.Length; - - byte[] descStr = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); - s.Write(descStr, 0, descStr.Length); - - while (n > 0) - { - m = n < LineLength ? n : LineLength; - - if (s_buf.Length - s_index < m) - { - s.Write(s_buf, 0, s_index); - s_index = 0; - } - - for (int i = 0; i < m; i++) - { - if (k == kn) - k = 0; - - s_buf[s_index++] = alu[k]; - k++; - } - - s_buf[s_index++] = (byte)'\n'; - n -= LineLength; - } - - if (s_index != 0) - s.Write(s_buf, 0, s_index); - } -} -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs deleted file mode 100644 index c7a786a77ef3..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux.csharp.cs +++ /dev/null @@ -1,186 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Robert F. Tobler - optimized based on java & C# by Enotus, Isaac Gouy, and Alp Toker - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.IO; -using System.Text; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ -public static class FastaRedux -{ -#if DEBUG - private const int Iterations = 1; -#else - const int Iterations = 5; -#endif - - public static int Main(string[] args) - { - AccumulateAndScale(s_homoSapiens); - AccumulateAndScale(s_IUB); - int n = args.Length > 0 ? Int32.Parse(args[0]) : 2500; - using (Stream s = Console.OpenStandardOutput()) - { - s.WriteRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2); - s.WriteRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3); - s.WriteRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5); - } - return 100; - } - - [Benchmark] - public static void Bench() - { - int n = 2500000; - AccumulateAndScale(s_homoSapiens); - AccumulateAndScale(s_IUB); - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - using (Stream s = Stream.Null) - { - for (int i = 0; i < Iterations; i++) - { - s.WriteRepeatFasta("ONE", "Homo sapiens alu", Encoding.ASCII.GetBytes(s_ALU), n * 2); - s.WriteRandomFasta("TWO", "IUB ambiguity codes", s_IUB, n * 3); - s.WriteRandomFasta("THREE", "Homo sapiens frequency", s_homoSapiens, n * 5); - } - } - } - } - } - - private const int LINE_LEN = 60; - private const int BUF_LEN = 64 * 1024; - private const byte LF = (byte)'\n'; - - private const int LOOKUP_LEN = 1024; - private const double LOOKUP_SCALE = LOOKUP_LEN - 1; - - private static readonly string s_ALU = - "GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGG" + - "GAGGCCGAGGCGGGCGGATCACCTGAGGTCAGGAGTTCGAGA" + - "CCAGCCTGGCCAACATGGTGAAACCCCGTCTCTACTAAAAAT" + - "ACAAAAATTAGCCGGGCGTGGTGGCGCGCGCCTGTAATCCCA" + - "GCTACTCGGGAGGCTGAGGCAGGAGAATCGCTTGAACCCGGG" + - "AGGCGGAGGTTGCAGTGAGCCGAGATCGCGCCACTGCACTCC" + - "AGCCTGGGCGACAGAGCGAGACTCCGTCTCAAAAA"; - - private struct Freq - { - public double P; - public byte C; - - public Freq(char c, double p) { C = (byte)c; P = p; } - } - - private static Freq[] s_IUB = { - new Freq('a', 0.27), new Freq('c', 0.12), new Freq('g', 0.12), - new Freq('t', 0.27), new Freq('B', 0.02), new Freq('D', 0.02), - new Freq('H', 0.02), new Freq('K', 0.02), new Freq('M', 0.02), - new Freq('N', 0.02), new Freq('R', 0.02), new Freq('S', 0.02), - new Freq('V', 0.02), new Freq('W', 0.02), new Freq('Y', 0.02), - }; - - private static Freq[] s_homoSapiens = { - new Freq ('a', 0.3029549426680), new Freq ('c', 0.1979883004921), - new Freq ('g', 0.1975473066391), new Freq ('t', 0.3015094502008), - }; - - private static void AccumulateAndScale(Freq[] a) - { - double cp = 0.0; - for (int i = 0; i < a.Length; i++) - a[i].P = (cp += a[i].P) * LOOKUP_SCALE; - a[a.Length - 1].P = LOOKUP_SCALE; - } - - private static byte[] s_buf = new byte[BUF_LEN]; - - private static int WriteDesc(this byte[] buf, string id, string desc) - { - var ds = Encoding.ASCII.GetBytes(">" + id + " " + desc + "\n"); - for (int i = 0; i < ds.Length; i++) buf[i] = ds[i]; - return BUF_LEN - ds.Length; - } - - private static int Min(int a, int b) { return a < b ? a : b; } - - private static void WriteRepeatFasta( - this Stream s, string id, string desc, byte[] alu, int nr) - { - int alen = alu.Length; - int ar = alen, br = s_buf.WriteDesc(id, desc), lr = LINE_LEN; - while (nr > 0) - { - int r = Min(Min(nr, lr), Min(ar, br)); - for (int ai = alen - ar, bi = BUF_LEN - br, be = bi + r; - bi < be; bi++, ai++) - s_buf[bi] = alu[ai]; - nr -= r; lr -= r; br -= r; ar -= r; - if (ar == 0) ar = alen; - if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; } - if (lr == 0) { s_buf[BUF_LEN - (br--)] = LF; lr = LINE_LEN; } - if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; } - } - if (lr < LINE_LEN) s_buf[BUF_LEN - (br--)] = LF; - if (br < BUF_LEN) s.Write(s_buf, 0, BUF_LEN - br); - } - - private static Freq[] s_lookup = new Freq[LOOKUP_LEN]; - - private static void CreateLookup(Freq[] fr) - { - for (int i = 0, j = 0; i < LOOKUP_LEN; i++) - { - while (fr[j].P < i) j++; - s_lookup[i] = fr[j]; - } - } - - private const int IM = 139968; - private const int IA = 3877; - private const int IC = 29573; - private const double SCALE = LOOKUP_SCALE / IM; - - private static int s_last = 42; - - private static void WriteRandomFasta( - this Stream s, string id, string desc, Freq[] fr, int nr) - { - CreateLookup(fr); - int br = s_buf.WriteDesc(id, desc), lr = LINE_LEN; - while (nr > 0) - { - int r = Min(Min(nr, lr), br); - for (int bi = BUF_LEN - br, be = bi + r; bi < be; bi++) - { - double p = SCALE * (s_last = (s_last * IA + IC) % IM); - int ai = (int)p; if (s_lookup[ai].P < p) ai++; - s_buf[bi] = s_lookup[ai].C; - } - nr -= r; lr -= r; br -= r; - if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; } - if (lr == 0) { s_buf[BUF_LEN - (br--)] = LF; lr = LINE_LEN; } - if (br == 0) { s.Write(s_buf, 0, BUF_LEN); br = BUF_LEN; } - } - if (lr < LINE_LEN) s_buf[BUF_LEN - (br--)] = LF; - if (br < BUF_LEN) s.Write(s_buf, 0, BUF_LEN - br); - } -} -} - diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/harness-helpers.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/harness-helpers.cs new file mode 100644 index 000000000000..d7b9a5754ce9 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/harness-helpers.cs @@ -0,0 +1,102 @@ +// 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. + +// Helper functionality to locate inputs and find outputs for +// k-nucleotide benchmark in CoreCLR test harness + +using System; +using System.IO; +using System.Text; + +namespace BenchmarksGame +{ + class TestHarnessHelpers + { + public string InputFile; + public int[] expectedCountLetter; + public int[] expectedCountPairs; + public int[] expectedCountFragments; + public int[][] expectedFrequencies; + + public TestHarnessHelpers(bool bigInput, [System.Runtime.CompilerServices.CallerFilePath] string csFileName = "") + { + if (bigInput) + { + InputFile = FindInputFile("knucleotide-input-big.txt", csFileName); + expectedCountLetter = new int[] { 302923, 301375, 198136, 197566 }; + expectedCountPairs = new int[] { 91779, 91253, 91225, 90837, 60096, 60030, 59889, 59795, 59756, 59713, 59572, 59557, 39203, 39190, 39081, 39023 }; + expectedCountFragments = new int[] { 11765, 3572, 380, 7, 7 }; + } + else + { + InputFile = FindInputFile("knucleotide-input.txt", csFileName); + expectedCountLetter = new int[] { 1576, 1480, 974, 970 }; + expectedCountPairs = new int[] { 496, 480, 470, 420, 316, 315, 310, 302, 298, 292, 273, 272, 202, 201, 185, 167 }; + expectedCountFragments = new int[] { 54, 24, 4, 0, 0 }; + } + expectedFrequencies = new int[][] { expectedCountLetter, expectedCountPairs }; + } + + public string FindInputFile(string inputFile, string csFileName) + { + string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); + + if (CoreRoot == null) + { + Console.WriteLine("This benchmark requries CORE_ROOT to be set"); + return null; + } + + // The convention is that the csproj file has the same name as the cs file. + string projectName = Path.GetFileNameWithoutExtension(csFileName); + int slashIndex = projectName.LastIndexOfAny(new char[] { '/', '\\' }); + if (slashIndex != -1) + { + // csFileName was generated by the C# compiler, which may have run on + // a different host system with different path separator than the + // currently executing host, which dictates GetFileNameWithoutExtension's + // behavior... so hope that the slash here is a cross-host path separator, + // and chop of what were likely direcotires. + projectName = projectName.Substring(slashIndex + 1); + } + + // Normal testing -- input file will end up next to the assembly + // and CoreRoot points at the test overlay dir + string[] pathPartsNormal = new string[] { + CoreRoot, "..", "..", "JIT", "Performance", + "CodeQuality", "BenchmarksGame", "k-nucleotide", projectName, inputFile + }; + + string inputPathNormal = Path.Combine(pathPartsNormal); + + // Perf testing -- input file will end up next to the assembly + // and CoreRoot points at this directory + string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; + + string inputPathPerf = Path.Combine(pathPartsPerf); + + string inputPath = null; + + if (File.Exists(inputPathNormal)) + { + inputPath = inputPathNormal; + } + else if (File.Exists(inputPathPerf)) + { + inputPath = inputPathPerf; + } + + if (inputPath != null) + { + Console.WriteLine("Using input file {0}", inputFile); + } + else + { + throw new Exception($"Unable to find input file {inputFile}. Tried {inputPathNormal} and {inputPathPerf}; csFileName was {csFileName}, so projectName was {projectName}."); + } + + return inputPath; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.cs new file mode 100644 index 000000000000..96d49f702ef6 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.cs @@ -0,0 +1,230 @@ +// 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. + +// Adapted from k-nucleotide C# .NET Core program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=csharpcore&id=1 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/knucleotide/knucleotide.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + * + * byte processing version using C# *3.0 idioms by Robert F. Tobler + */ + +using System; +using System.IO; +using System.Collections.Generic; +using System.Text; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureGCCounts] + +namespace BenchmarksGame +{ + + public struct ByteString : IEquatable + { + public byte[] Array; + public int Start; + public int Length; + + public ByteString(byte[] array, int start, int length) + { + Array = array; Start = start; Length = length; + } + + public ByteString(string text) + { + Start = 0; Length = text.Length; + Array = Encoding.ASCII.GetBytes(text); + } + + public override int GetHashCode() + { + if (Length < 1) return 0; + int hc = Length ^ (Array[Start] << 24); if (Length < 2) return hc; + hc ^= Array[Start + Length - 1] << 20; if (Length < 3) return hc; + for (int c = Length - 2; c > 0; c--) + hc ^= Array[Start + c] << (c & 0xf); + return hc; + } + + public bool Equals(ByteString other) + { + if (Length != other.Length) return false; + for (int i = 0; i < Length; i++) + if (Array[Start + i] != other.Array[other.Start + i]) return false; + return true; + } + + public override string ToString() + { + return Encoding.ASCII.GetString(Array, Start, Length); + } + } + + public static class Extensions + { + public static byte[] GetBytes(this List input) + { + int count = 0; + for (int i = 0; i < input.Count; i++) count += input[i].Length; + var byteArray = new byte[count]; + count = 0; + for (int i = 0; i < input.Count; i++) + { + string line = input[i]; + Encoding.ASCII.GetBytes(line, 0, line.Length, byteArray, count); + count += line.Length; + } + return byteArray; + } + } + + public class KNucleotide_1 + { + + public static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + + using (var inputFile = new FileStream(helpers.InputFile, FileMode.Open)) + { + if (!Bench(inputFile, helpers, true)) + { + return -1; + } + } + + return 100; + } + + [Benchmark(InnerIterationCount = 3)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + bool ok = true; + + Benchmark.Iterate(() => + { + using (var inputFile = new FileStream(helpers.InputFile, FileMode.Open)) + { + ok &= Bench(inputFile, helpers, false); + } + }); + Assert.True(ok); + } + + static bool Bench(Stream inputStream, TestHarnessHelpers helpers, bool verbose) + { + string line; + StreamReader source = new StreamReader(inputStream); + var input = new List(); + + while ((line = source.ReadLine()) != null) + if (line[0] == '>' && line.Substring(1, 5) == "THREE") + break; + + while ((line = source.ReadLine()) != null) + { + char c = line[0]; + if (c == '>') break; + if (c != ';') input.Add(line.ToUpper()); + } + + KNucleotide kn = new KNucleotide(input.GetBytes()); + input = null; + bool ok = true; + for (int f = 1; f < 3; f++) + ok &= kn.WriteFrequencies(f, helpers.expectedFrequencies[f - 1], verbose); + int i = 0; + foreach (var seq in + new[] { "GGT", "GGTA", "GGTATT", "GGTATTTTAATT", + "GGTATTTTAATTTATAGT"}) + ok &= kn.WriteCount(seq, helpers.expectedCountFragments[i++], verbose); + + return ok; + } + } + + public class KNucleotide + { + + private class Count + { + public int V; + public Count(int v) { V = v; } + } + + private Dictionary frequencies + = new Dictionary(); + private byte[] sequence; + + public KNucleotide(byte[] s) { sequence = s; } + + public bool WriteFrequencies(int length, int[] expectedCounts, bool verbose) + { + GenerateFrequencies(length); + var items = new List>(frequencies); + items.Sort(SortByFrequencyAndCode); + double percent = 100.0 / (sequence.Length - length + 1); + bool ok = true; + int i = 0; + foreach (var item in items) + { + ok &= (item.Value.V == expectedCounts[i++]); + if (verbose) + { + Console.WriteLine("{0} {1:f3}", + item.Key.ToString(), item.Value.V * percent); + } + } + if (verbose) Console.WriteLine(); + return ok; + } + + public bool WriteCount(string fragment, int expectedCount, bool verbose) + { + GenerateFrequencies(fragment.Length); + Count count; + if (!frequencies.TryGetValue(new ByteString(fragment), out count)) + count = new Count(0); + if (verbose) Console.WriteLine("{0}\t{1}", count.V, fragment); + return (count.V == expectedCount); + } + + private void GenerateFrequencies(int length) + { + frequencies.Clear(); + for (int frame = 0; frame < length; frame++) + KFrequency(frame, length); + } + + private void KFrequency(int frame, int k) + { + int n = sequence.Length - k + 1; + for (int i = frame; i < n; i += k) + { + var key = new ByteString(sequence, i, k); + Count count; + if (frequencies.TryGetValue(key, out count)) + count.V++; + else + frequencies[key] = new Count(1); + } + } + + int SortByFrequencyAndCode( + KeyValuePair i0, + KeyValuePair i1) + { + int order = i1.Value.V.CompareTo(i0.Value.V); + if (order != 0) return order; + return i0.Key.ToString().CompareTo(i1.Key.ToString()); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.csproj similarity index 91% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.csproj index 89c8ad5c47ea..d65aaae57d6b 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-1.csproj @@ -1,11 +1,11 @@ - + Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {72C2713D-C5A4-4BE0-82F3-3B7EEB4DB574} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -30,7 +30,8 @@ - + + @@ -45,4 +46,4 @@ $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json - \ No newline at end of file + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.cs new file mode 100644 index 000000000000..e6dd21243f54 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.cs @@ -0,0 +1,333 @@ +// 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. + +// Adapted from k-nucleotide C# .NET Core #9 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=csharpcore&id=9 +// aka (as of 2017-09-01) rev 1.1 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/knucleotide/knucleotide.csharp-9.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + submitted by Josh Goldfoot + Modified to reduce memory and do more in parallel by Anthony Lloyd + */ + +using System; +using System.IO; +using System.Text; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Runtime.CompilerServices; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] +[assembly: MeasureGCCounts] + +namespace BenchmarksGame +{ + class Wrapper { public int v = 1; } + public static class KNucleotide_9 + { + const int BLOCK_SIZE = 1024 * 1024 * 8; + static List threeBlocks = new List(); + static int threeStart, threeEnd; + static byte[] tonum = new byte[256]; + static char[] tochar = new char[] { 'A', 'C', 'G', 'T' }; + + static int read(Stream stream, byte[] buffer, int offset, int count) + { + var bytesRead = stream.Read(buffer, offset, count); + return bytesRead == count ? offset + count + : bytesRead == 0 ? offset + : read(stream, buffer, offset + bytesRead, count - bytesRead); + } + + static int find(byte[] buffer, byte[] toFind, int i, ref int matchIndex) + { + if (matchIndex == 0) + { + i = Array.IndexOf(buffer, toFind[0], i); + if (i == -1) return -1; + matchIndex = 1; + return find(buffer, toFind, i + 1, ref matchIndex); + } + else + { + int bl = buffer.Length, fl = toFind.Length; + while (i < bl && matchIndex < fl) + { + if (buffer[i++] != toFind[matchIndex++]) + { + matchIndex = 0; + return find(buffer, toFind, i, ref matchIndex); + } + } + return matchIndex == fl ? i : -1; + } + } + + static void loadThreeData(Stream stream) + { + // find three sequence + int matchIndex = 0; + var toFind = new[] { (byte)'>', (byte)'T', (byte)'H', (byte)'R', (byte)'E', (byte)'E' }; + var buffer = new byte[BLOCK_SIZE]; + do + { + threeEnd = read(stream, buffer, 0, BLOCK_SIZE); + threeStart = find(buffer, toFind, 0, ref matchIndex); + } while (threeStart == -1); + + // Skip to end of line + matchIndex = 0; + toFind = new[] { (byte)'\n' }; + threeStart = find(buffer, toFind, threeStart, ref matchIndex); + while (threeStart == -1) + { + threeEnd = read(stream, buffer, 0, BLOCK_SIZE); + threeStart = find(buffer, toFind, 0, ref matchIndex); + } + threeBlocks.Add(buffer); + + if (threeEnd != BLOCK_SIZE) // Needs to be at least 2 blocks + { + var bytes = threeBlocks[0]; + for (int i = threeEnd; i < bytes.Length; i++) + bytes[i] = 255; + threeEnd = 0; + threeBlocks.Add(Array.Empty()); + return; + } + + // find next seq or end of input + matchIndex = 0; + toFind = new[] { (byte)'>' }; + threeEnd = find(buffer, toFind, threeStart, ref matchIndex); + while (threeEnd == -1) + { + buffer = new byte[BLOCK_SIZE]; + var bytesRead = read(stream, buffer, 0, BLOCK_SIZE); + threeEnd = bytesRead == BLOCK_SIZE ? find(buffer, toFind, 0, ref matchIndex) + : bytesRead; + threeBlocks.Add(buffer); + } + + if (threeStart + 18 > BLOCK_SIZE) // Key needs to be in the first block + { + byte[] block0 = threeBlocks[0], block1 = threeBlocks[1]; + Buffer.BlockCopy(block0, threeStart, block0, threeStart - 18, BLOCK_SIZE - threeStart); + Buffer.BlockCopy(block1, 0, block0, BLOCK_SIZE - 18, 18); + for (int i = 0; i < 18; i++) block1[i] = 255; + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void check(Dictionary dict, ref long rollingKey, byte nb, long mask) + { + if (nb == 255) return; + rollingKey = ((rollingKey & mask) << 2) | nb; + Wrapper w; + if (dict.TryGetValue(rollingKey, out w)) + w.v++; + else + dict[rollingKey] = new Wrapper(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static void checkEnding(Dictionary dict, ref long rollingKey, byte b, byte nb, long mask) + { + if (nb == b) + { + Wrapper w; + if (dict.TryGetValue(rollingKey, out w)) + w.v++; + else + dict[rollingKey] = new Wrapper(); + rollingKey = ((rollingKey << 2) | nb) & mask; + } + else if (nb != 255) + { + rollingKey = ((rollingKey << 2) | nb) & mask; + } + } + + static Task count(int l, long mask, Func, string> summary) + { + return Task.Run(() => + { + long rollingKey = 0; + var firstBlock = threeBlocks[0]; + var start = threeStart; + while (--l > 0) rollingKey = (rollingKey << 2) | firstBlock[start++]; + var dict = new Dictionary(); + for (int i = start; i < firstBlock.Length; i++) + check(dict, ref rollingKey, firstBlock[i], mask); + + int lastBlockId = threeBlocks.Count - 1; + for (int bl = 1; bl < lastBlockId; bl++) + { + var bytes = threeBlocks[bl]; + for (int i = 0; i < bytes.Length; i++) + check(dict, ref rollingKey, bytes[i], mask); + } + + var lastBlock = threeBlocks[lastBlockId]; + for (int i = 0; i < threeEnd; i++) + check(dict, ref rollingKey, lastBlock[i], mask); + return summary(dict); + }); + } + + static Dictionary countEnding(int l, long mask, byte b) + { + long rollingKey = 0; + var firstBlock = threeBlocks[0]; + var start = threeStart; + while (--l > 0) rollingKey = (rollingKey << 2) | firstBlock[start++]; + var dict = new Dictionary(); + for (int i = start; i < firstBlock.Length; i++) + checkEnding(dict, ref rollingKey, b, firstBlock[i], mask); + + int lastBlockId = threeBlocks.Count - 1; + for (int bl = 1; bl < lastBlockId; bl++) + { + var bytes = threeBlocks[bl]; + for (int i = 0; i < bytes.Length; i++) + checkEnding(dict, ref rollingKey, b, bytes[i], mask); + } + + var lastBlock = threeBlocks[lastBlockId]; + for (int i = 0; i < threeEnd; i++) + checkEnding(dict, ref rollingKey, b, lastBlock[i], mask); + return dict; + } + + static Task count4(int l, long mask, Func, string> summary) + { + return Task.Factory.ContinueWhenAll( + new[] { + Task.Run(() => countEnding(l, mask, 0)), + Task.Run(() => countEnding(l, mask, 1)), + Task.Run(() => countEnding(l, mask, 2)), + Task.Run(() => countEnding(l, mask, 3)) + } + , dicts => + { + var d = new Dictionary(dicts.Sum(i => i.Result.Count)); + for (int i = 0; i < dicts.Length; i++) + foreach (var kv in dicts[i].Result) + d[(kv.Key << 2) | (long)i] = kv.Value; + return summary(d); + }); + } + + static string writeFrequencies(Dictionary freq, int fragmentLength, int[] expected, ref bool ok) + { + var sb = new StringBuilder(); + double percent = 100.0 / freq.Values.Sum(i => i.v); + int idx = 0; + foreach (var kv in freq.OrderByDescending(i => i.Value.v)) + { + ok &= (kv.Value.v == expected[idx++]); + var keyChars = new char[fragmentLength]; + var key = kv.Key; + for (int i = keyChars.Length - 1; i >= 0; --i) + { + keyChars[i] = tochar[key & 0x3]; + key >>= 2; + } + sb.Append(keyChars); + sb.Append(" "); + sb.AppendLine((kv.Value.v * percent).ToString("F3")); + } + return sb.ToString(); + } + + static string writeCount(Dictionary dictionary, string fragment, int expected, ref bool ok) + { + long key = 0; + for (int i = 0; i < fragment.Length; ++i) + key = (key << 2) | tonum[fragment[i]]; + Wrapper w; + var n = dictionary.TryGetValue(key, out w) ? w.v : 0; + ok &= (n == expected); + return string.Concat(n.ToString(), "\t", fragment); + } + + public static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + bool ok = Bench(helpers, true); + + return (ok ? 100 : -1); + } + + [Benchmark(InnerIterationCount = 10)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + bool ok = true; + + Benchmark.Iterate(() => + { + ok &= Bench(helpers, false); + }); + Assert.True(ok); + } + + static bool Bench(TestHarnessHelpers helpers, bool verbose) + { + // Reset static state + threeBlocks.Clear(); + threeStart = 0; + threeEnd = 0; + + tonum['c'] = 1; tonum['C'] = 1; + tonum['g'] = 2; tonum['G'] = 2; + tonum['t'] = 3; tonum['T'] = 3; + tonum['\n'] = 255; tonum['>'] = 255; tonum[255] = 255; + + using (var inputStream = new FileStream(helpers.InputFile, FileMode.Open)) + { + loadThreeData(inputStream); + } + + Parallel.ForEach(threeBlocks, bytes => + { + for (int i = 0; i < bytes.Length; i++) + bytes[i] = tonum[bytes[i]]; + }); + + bool ok = true; + + var task18 = count4(18, 0x7FFFFFFFF, d => writeCount(d, "GGTATTTTAATTTATAGT", helpers.expectedCountFragments[4], ref ok)); + var task12 = count4(12, 0x7FFFFF, d => writeCount(d, "GGTATTTTAATT", helpers.expectedCountFragments[3], ref ok)); + var task6 = count(6, 0x3FF, d => writeCount(d, "GGTATT", helpers.expectedCountFragments[2], ref ok)); + var task4 = count(4, 0x3F, d => writeCount(d, "GGTA", helpers.expectedCountFragments[1], ref ok)); + var task3 = count(3, 0xF, d => writeCount(d, "GGT", helpers.expectedCountFragments[0], ref ok)); + var task2 = count(2, 0x3, d => writeFrequencies(d, 2, helpers.expectedFrequencies[1], ref ok)); + var task1 = count(1, 0, d => writeFrequencies(d, 1, helpers.expectedFrequencies[0], ref ok)); + + if (verbose) + { + Console.Out.WriteLineAsync(task1.Result); + Console.Out.WriteLineAsync(task2.Result); + Console.Out.WriteLineAsync(task3.Result); + Console.Out.WriteLineAsync(task4.Result); + Console.Out.WriteLineAsync(task6.Result); + Console.Out.WriteLineAsync(task12.Result); + Console.Out.WriteLineAsync(task18.Result); + } + else + { + Task.WaitAll(task1, task2, task3, task4, task6, task12, task18); + } + + return ok; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.csproj new file mode 100644 index 000000000000..9e72ba4a0f11 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-9.csproj @@ -0,0 +1,49 @@ + + + + + Debug + AnyCPU + 2.0 + {06749069-420D-4F3E-8977-49B720EFE4CB} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + Always + + + Always + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.cs deleted file mode 100644 index 3325a619265e..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide.cs +++ /dev/null @@ -1,311 +0,0 @@ -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - * - * submitted by Josh Goldfoot - * - */ - -using System; -using System.IO; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Microsoft.Xunit.Performance; -using Xunit; - -[assembly: OptimizeForBenchmarks] -[assembly: MeasureGCCounts] - -namespace BenchmarksGame -{ - -public class knucleotide -{ -#if DEBUG - const int Iterations = 1; - const string InputFile = "knucleotide-input.txt"; - static int[] expectedCountLetter = new int[] { 1480, 974, 970, 1576 }; - static int[] expectedCountPairs = new int[] { 420, 272, 292, 496, 273, 202, 201, 298, 316, 185, 167, 302, 470, 315, 310, 480 }; - static int[] expectedCountFragments = new int[] { 54, 24, 4, 0, 0 }; -#else - const int Iterations = 10; - const string InputFile = "knucleotide-input-big.txt"; - static int[] expectedCountLetter = new int[] { 302923, 198136, 197566, 301375 }; - static int[] expectedCountPairs = new int[] { 91779, 60030, 59889, 91225, 60096, 39203, 39081, 59756, 59795, 39190, 39023, 59557, 91253, 59713, 59572, 90837 }; - static int[] expectedCountFragments = new int[] { 11765, 3572, 380, 7, 7 }; -#endif - - - static string FindInput(string s) - { - string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); - - if (CoreRoot == null) - { - Console.WriteLine("This benchmark requries CORE_ROOT to be set"); - return null; - } - - string inputFile = s ?? InputFile; - - // Normal testing -- input file will end up next to the assembly - // and CoreRoot points at the test overlay dir - string[] pathPartsNormal = new string[] { - CoreRoot, "..", "..", "JIT", "Performance", - "CodeQuality", "BenchmarksGame", "k-nucleotide", "k-nucleotide", inputFile - }; - - string inputPathNormal = Path.Combine(pathPartsNormal); - - // Perf testing -- input file will end up next to the assembly - // and CoreRoot points at this directory - string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; - - string inputPathPerf = Path.Combine(pathPartsPerf); - - string inputPath = null; - - if (File.Exists(inputPathNormal)) - { - inputPath = inputPathNormal; - } - else if (File.Exists(inputPathPerf)) - { - inputPath = inputPathPerf; - } - - if (inputPath != null) - { - Console.WriteLine("Using input file {0}", inputPath); - } - else - { - Console.WriteLine("Unable to find input file {0}", inputFile); - } - - return inputPath; - } - - public static int Main(string[] args) - { - int iterations = Iterations; - - string inputFile = FindInput(InputFile); - if (inputFile == null) - { - throw new Exception("unable to find input"); - } - - PrepareLookups(); - var source = new FileStream(inputFile, FileMode.Open); - var buffer = GetBytesForThirdSequence(source); - var fragmentLengths = new[] { 1, 2, 3, 4, 6, 12, 18 }; - var dicts = - (from fragmentLength in fragmentLengths.AsParallel() - select CountFrequency(buffer, fragmentLength)).ToArray(); - source.Dispose(); - int res = 100; - for (ulong i = 0; i < 4; ++i){ - if (dicts[0][i].V != expectedCountLetter[i]){ - res = -1; - } - } - for (ulong i = 0; i < 16; ++i){ - if (dicts[1][i].V != expectedCountPairs[i]){ - res = -1; - } - } - int buflen = dicts[0].Values.Sum(x => x.V); - WriteFrequencies(dicts[0], buflen, 1); - WriteFrequencies(dicts[1], buflen, 2); - if (WriteCount(dicts[2], "GGT") != expectedCountFragments[0]) { res = -1; } - if (WriteCount(dicts[3], "GGTA") != expectedCountFragments[1]) { res = -1; } - if (WriteCount(dicts[4], "GGTATT") != expectedCountFragments[2]) { res = -1; } - if (WriteCount(dicts[5], "GGTATTTTAATT") != expectedCountFragments[3]) { res = -1; } - if (WriteCount(dicts[6], "GGTATTTTAATTTATAGT") != expectedCountFragments[4]) { res = -1; } - //Console.ReadKey(); - return res; - } - - private static void WriteFrequencies(Dictionary freq, int buflen, int fragmentLength) - { - - double percent = 100.0 / (buflen - fragmentLength + 1); - foreach (var line in (from k in freq.Keys - orderby freq[k].V descending - select string.Format("{0} {1:f3}", PrintKey(k, fragmentLength), - (freq.ContainsKey(k) ? freq[k].V : 0) * percent))) - Console.WriteLine(line); - Console.WriteLine(); - } - - private static int WriteCount(Dictionary dictionary, string fragment) - { - ulong key = 0; - var keybytes = Encoding.ASCII.GetBytes(fragment.ToLower()); - for (int i = 0; i < keybytes.Length; i++) - { - key <<= 2; - key |= tonum[keybytes[i]]; - } - Wrapper w; - int count = dictionary.TryGetValue(key, out w) ? w.V : 0; - Console.WriteLine("{0}\t{1}", - count, - fragment); - return count; - } - - private static string PrintKey(ulong key, int fragmentLength) - { - char[] items = new char[fragmentLength]; - for (int i = 0; i < fragmentLength; ++i) - { - items[fragmentLength - i - 1] = tochar[key & 0x3]; - key >>= 2; - } - return new string(items); - } - - private static Dictionary CountFrequency(byte[] buffer, int fragmentLength) - { - var dictionary = new Dictionary(); - ulong rollingKey = 0; - ulong mask = 0; - int cursor; - for (cursor = 0; cursor < fragmentLength - 1; cursor++) - { - rollingKey <<= 2; - rollingKey |= tonum[buffer[cursor]]; - mask = (mask << 2) + 3; - } - mask = (mask << 2) + 3; - int stop = buffer.Length; - Wrapper w; - byte cursorByte; - while (cursor < stop) - { - if ((cursorByte = buffer[cursor++]) < (byte)'a') - cursorByte = buffer[cursor++]; - rollingKey = ((rollingKey << 2) & mask) | tonum[cursorByte]; - if (dictionary.TryGetValue(rollingKey, out w)) - w.V++; - else - dictionary.Add(rollingKey, new Wrapper(1)); - } - return dictionary; - } - - private static byte[] GetBytesForThirdSequence(FileStream source) - { - const int buffersize = 2500120; - byte[] threebuffer = null; - var buffer = new byte[buffersize]; - int amountRead, threebuflen, indexOfFirstByteInThreeSequence, indexOfGreaterThan, threepos, tocopy; - amountRead = threebuflen = indexOfFirstByteInThreeSequence = indexOfGreaterThan = threepos = tocopy = 0; - bool threeFound = false; - //var source = new FileStream(inputFile, FileMode.Open); - source.Seek(0, SeekOrigin.Begin); - while (!threeFound && (amountRead = source.Read(buffer, 0, buffersize)) > 0) - { - indexOfGreaterThan = Array.LastIndexOf(buffer, (byte)'>'); - threeFound = (indexOfGreaterThan > -1 && - buffer[indexOfGreaterThan + 1] == (byte)'T' && - buffer[indexOfGreaterThan + 2] == (byte)'H'); - if (threeFound) - { - threepos += indexOfGreaterThan; - threebuflen = threepos - 48; - threebuffer = new byte[threebuflen]; - indexOfFirstByteInThreeSequence = Array.IndexOf(buffer, 10, indexOfGreaterThan) + 1; - tocopy = amountRead - indexOfFirstByteInThreeSequence; - if (amountRead < buffersize) - tocopy -= 1; - Buffer.BlockCopy(buffer, indexOfFirstByteInThreeSequence, threebuffer, 0, tocopy); - buffer = null; - } - else - threepos += amountRead; - } - int toread = threebuflen - tocopy; - source.Read(threebuffer, tocopy, toread); - return threebuffer; - } - - private static byte[] tonum = new byte[256]; - private static char[] tochar = new char[4]; - private static void PrepareLookups() - { - tonum['a'] = 0; - tonum['c'] = 1; - tonum['g'] = 2; - tonum['t'] = 3; - tochar[0] = 'A'; - tochar[1] = 'C'; - tochar[2] = 'G'; - tochar[3] = 'T'; - } - - [Benchmark(InnerIterationCount=Iterations)] - public static void Bench_Parallel() - { - PrepareLookups(); - string inputFile = FindInput(InputFile); - var source = new FileStream(inputFile, FileMode.Open); - - if (inputFile == null) - { - throw new Exception("unable to find input"); - } - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Benchmark.InnerIterationCount; ++i) - { - var buffer = GetBytesForThirdSequence(source); - var fragmentLengths = new[] { 1, 2, 3, 4, 6, 12, 18 }; - var dicts = - (from fragmentLength in fragmentLengths.AsParallel() - select CountFrequency(buffer, fragmentLength)).ToArray(); - } - } - } - source.Dispose(); - } - [Benchmark(InnerIterationCount=Iterations)] - public static void Bench_No_Parallel() - { - string inputFile = FindInput(InputFile); - var source = new FileStream(inputFile, FileMode.Open); - - if (inputFile == null) - { - throw new Exception("unable to find input"); - } - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Benchmark.InnerIterationCount; ++i) - { - PrepareLookups(); - var buffer = GetBytesForThirdSequence(source); - var fragmentLengths = new[] { 1, 2, 3, 4, 6, 12, 18 }; - var dicts = - (from fragmentLength in fragmentLengths - select CountFrequency(buffer, fragmentLength)).ToArray(); - } - } - } - source.Dispose(); - } -} - -public class Wrapper -{ - public int V; - public Wrapper(int v) { V = v; } -} - -} \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.cs new file mode 100644 index 000000000000..fa55666be5de --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.cs @@ -0,0 +1,138 @@ +// 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. + +// Adapted from mandelbrot C# .NET Core #2 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=csharpcore&id=2 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/mandelbrot/mandelbrot.csharp-2.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + * + * Adapted by Antti Lankila from the earlier Isaac Gouy's implementation + */ + +using System; +using System.IO; +using System.Security.Cryptography; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class Mandelbrot_2 + { + public static int Main(String[] args) + { + int width = 80; + if (args.Length > 0) + width = Int32.Parse(args[0]); + + int lineLen = (width - 1) / 8 + 1; + var bytes = new byte[width * lineLen]; + var memStream = new MemoryStream(bytes); + + DoBench(width, memStream, true); + + if (!MatchesChecksum(bytes, "3B-EF-65-05-1D-39-7F-9B-96-8D-EF-98-BF-06-CE-74")) + { + return -1; + } + return 100; + } + + // Commented out data left in source to provide checksums for each case + + [Benchmark] + //[InlineData(1000, "B2-13-51-CE-B0-29-2C-4E-75-5E-91-19-18-E4-0C-D9")] + //[InlineData(2000, "5A-21-55-9B-7B-18-2F-34-9B-33-C5-F9-B5-2C-40-56")] + //[InlineData(3000, "E5-82-85-0A-3C-89-69-B1-A8-21-63-52-75-B3-C8-33")] + [InlineData(4000, "C7-E6-66-43-66-73-F8-A8-D3-B4-D7-97-2F-FC-A1-D3")] + //[InlineData(5000, "6D-36-F1-F6-37-8F-34-EB-52-F9-2D-11-89-12-B2-2F")] + //[InlineData(6000, "8B-05-78-EB-2E-0E-98-F2-C7-39-76-ED-0F-A9-D2-B8")] + //[InlineData(7000, "01-F8-F2-2A-AB-70-C7-BA-E3-64-19-E7-D2-84-DF-57")] + //[InlineData(8000, "C8-ED-D7-FB-65-66-3A-D9-C6-04-9E-96-E8-CA-4F-2C")] + public static void Bench(int width, string checksum) + { + int lineLen = (width - 1) / 8 + 1; + byte[] bytes = null; + + Benchmark.Iterate(() => + { + bytes = new byte[width * lineLen]; + var memStream = new MemoryStream(bytes); + + DoBench(width, memStream, false); + }); + + Assert.True(MatchesChecksum(bytes, checksum)); + } + + static bool MatchesChecksum(byte[] bytes, string checksum) + { + using (var md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(bytes); + return (checksum == BitConverter.ToString(hash)); + } + } + + static void DoBench(int width, MemoryStream s, bool verbose) + { + int height = width; + int maxiter = 50; + double limit = 4.0; + + if (verbose) + { + Console.WriteLine("P4"); + Console.WriteLine("{0} {1}", width, height); + } + + for (int y = 0; y < height; y++) + { + int bits = 0; + int xcounter = 0; + double Ci = 2.0 * y / height - 1.0; + + for (int x = 0; x < width; x++) + { + double Zr = 0.0; + double Zi = 0.0; + double Cr = 2.0 * x / width - 1.5; + int i = maxiter; + + bits = bits << 1; + do + { + double Tr = Zr * Zr - Zi * Zi + Cr; + Zi = 2.0 * Zr * Zi + Ci; + Zr = Tr; + if (Zr * Zr + Zi * Zi > limit) + { + bits |= 1; + break; + } + } while (--i > 0); + + if (++xcounter == 8) + { + s.WriteByte((byte)(bits ^ 0xff)); + bits = 0; + xcounter = 0; + } + } + if (xcounter != 0) + s.WriteByte((byte)((bits << (8 - xcounter)) ^ 0xff)); + } + + if (verbose) + { + s.WriteTo(Console.OpenStandardOutput()); + } + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.csproj new file mode 100644 index 000000000000..c84799234ffb --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-2.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {18ED6F79-05F2-4302-B2B5-543A33C9A517} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.cs new file mode 100644 index 000000000000..e63ed2950417 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.cs @@ -0,0 +1,125 @@ +// 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. + +// Adapted from mandelbrot C# .NET Core #4 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=csharpcore&id=4 +// aka (as of 2017-09-01) rev 1.3 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/mandelbrot/mandelbrot.csharp-4.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + started with Java #2 program (Krause/Whipkey/Bennet/AhnTran/Enotus/Stalcup) + adapted for C# by Jan de Vaan + simplified and optimised to use TPL by Anthony Lloyd +*/ + +using System; +using System.Threading.Tasks; +using System.IO; +using System.Runtime.CompilerServices; +using System.Security.Cryptography; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class MandelBrot_4 + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + static byte getByte(double[] Crb, double Ciby, int x, int y) + { + int res = 0; + for (int i = 0; i < 8; i += 2) + { + double Crbx = Crb[x + i], Crbx1 = Crb[x + i + 1]; + double Zr1 = Crbx, Zr2 = Crbx1; + double Zi1 = Ciby, Zi2 = Ciby; + + int b = 0; + int j = 49; + do + { + double nZr1 = Zr1 * Zr1 - Zi1 * Zi1 + Crbx; + Zi1 = Zr1 * Zi1 + Zr1 * Zi1 + Ciby; + Zr1 = nZr1; + + double nZr2 = Zr2 * Zr2 - Zi2 * Zi2 + Crbx1; + Zi2 = Zr2 * Zi2 + Zr2 * Zi2 + Ciby; + Zr2 = nZr2; + + if (Zr1 * Zr1 + Zi1 * Zi1 > 4) { b |= 2; if (b == 3) break; } + if (Zr2 * Zr2 + Zi2 * Zi2 > 4) { b |= 1; if (b == 3) break; } + } while (--j > 0); + res = (res << 2) + b; + } + return (byte)(res ^ -1); + } + + public static int Main(String[] args) + { + var n = args.Length > 0 ? Int32.Parse(args[0]) : 80; + var data = DoBench(n); + Console.Out.WriteLine("P4\n{0} {0}", n); + Console.OpenStandardOutput().Write(data, 0, data.Length); + + if (!MatchesChecksum(data, "3B-EF-65-05-1D-39-7F-9B-96-8D-EF-98-BF-06-CE-74")) + { + return -1; + } + return 100; + } + + // Commented out data left in source to provide checksums for each case + + [Benchmark(InnerIterationCount = 7)] + //[InlineData(1000, "B2-13-51-CE-B0-29-2C-4E-75-5E-91-19-18-E4-0C-D9")] + //[InlineData(2000, "5A-21-55-9B-7B-18-2F-34-9B-33-C5-F9-B5-2C-40-56")] + //[InlineData(3000, "E5-82-85-0A-3C-89-69-B1-A8-21-63-52-75-B3-C8-33")] + [InlineData(4000, "C7-E6-66-43-66-73-F8-A8-D3-B4-D7-97-2F-FC-A1-D3")] + //[InlineData(5000, "6D-36-F1-F6-37-8F-34-EB-52-F9-2D-11-89-12-B2-2F")] + //[InlineData(6000, "8B-05-78-EB-2E-0E-98-F2-C7-39-76-ED-0F-A9-D2-B8")] + //[InlineData(7000, "01-F8-F2-2A-AB-70-C7-BA-E3-64-19-E7-D2-84-DF-57")] + //[InlineData(8000, "C8-ED-D7-FB-65-66-3A-D9-C6-04-9E-96-E8-CA-4F-2C")] + public static void Bench(int n, string checksum) + { + byte[] bytes = null; + + Benchmark.Iterate(() => + { + bytes = DoBench(n); + }); + + Assert.True(MatchesChecksum(bytes, checksum)); + } + + static bool MatchesChecksum(byte[] bytes, string checksum) + { + using (var md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(bytes); + return (checksum == BitConverter.ToString(hash)); + } + } + + static byte[] DoBench(int n) + { + double invN = 2.0 / n; + var Crb = new double[n + 7]; + for (int i = 0; i < n; i++) { Crb[i] = i * invN - 1.5; } + int lineLen = (n - 1) / 8 + 1; + var data = new byte[n * lineLen]; + Parallel.For(0, n, y => + { + var Ciby = y * invN - 1.0; + var offset = y * lineLen; + for (int x = 0; x < lineLen; x++) + data[offset + x] = getByte(Crb, Ciby, x * 8, y); + }); + return data; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.csproj new file mode 100644 index 000000000000..3ab35800e2db --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-4.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {4BF33255-0CAD-42CA-81F0-60E536BA4E9D} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.cs new file mode 100644 index 000000000000..9be89da2f026 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.cs @@ -0,0 +1,160 @@ +// 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. + +// Adapted from n-body C# .NET Core #3 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=nbody&lang=csharpcore&id=3 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/nbody/nbody.csharp-3.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 +// (also best-scoring single-threaded C# .NET Core version as of 2017-09-01) + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy, optimization and use of more C# idioms by Robert F. Tobler +*/ + +using System; +using Microsoft.Xunit.Performance; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class NBody_3 + { + public static int Main(String[] args) + { + int n = args.Length > 0 ? Int32.Parse(args[0]) : 10000; + bool success = Bench(n, true); + return (success ? 100 : -1); + } + + [Benchmark(InnerIterationCount = 2)] + public static void RunBench() + { + Benchmark.Iterate(() => Bench(5000000, false)); + } + + static bool Bench(int n, bool verbose) + { + NBodySystem bodies = new NBodySystem(); + double initialEnergy = bodies.Energy(); + if (verbose) Console.WriteLine("{0:f9}", initialEnergy); + for (int i = 0; i < n; i++) bodies.Advance(0.01); + double finalEnergy = bodies.Energy(); + if (verbose) Console.WriteLine("{0:f9}", finalEnergy); + double deltaEnergy = Math.Abs(initialEnergy - finalEnergy); + bool result = deltaEnergy < 1e-4; + if (verbose) Console.WriteLine("Energy {0} conserved", result ? "was" : "was not"); + return result; + } + } + + class Body { public double x, y, z, vx, vy, vz, mass; } + class Pair { public Body bi, bj; } + + class NBodySystem + { + private Body[] bodies; + private Pair[] pairs; + + const double Pi = 3.141592653589793; + const double Solarmass = 4 * Pi * Pi; + const double DaysPeryear = 365.24; + + public NBodySystem() + { + bodies = new Body[] { + new Body() { // Sun + mass = Solarmass, + }, + new Body() { // Jupiter + x = 4.84143144246472090e+00, + y = -1.16032004402742839e+00, + z = -1.03622044471123109e-01, + vx = 1.66007664274403694e-03 * DaysPeryear, + vy = 7.69901118419740425e-03 * DaysPeryear, + vz = -6.90460016972063023e-05 * DaysPeryear, + mass = 9.54791938424326609e-04 * Solarmass, + }, + new Body() { // Saturn + x = 8.34336671824457987e+00, + y = 4.12479856412430479e+00, + z = -4.03523417114321381e-01, + vx = -2.76742510726862411e-03 * DaysPeryear, + vy = 4.99852801234917238e-03 * DaysPeryear, + vz = 2.30417297573763929e-05 * DaysPeryear, + mass = 2.85885980666130812e-04 * Solarmass, + }, + new Body() { // Uranus + x = 1.28943695621391310e+01, + y = -1.51111514016986312e+01, + z = -2.23307578892655734e-01, + vx = 2.96460137564761618e-03 * DaysPeryear, + vy = 2.37847173959480950e-03 * DaysPeryear, + vz = -2.96589568540237556e-05 * DaysPeryear, + mass = 4.36624404335156298e-05 * Solarmass, + }, + new Body() { // Neptune + x = 1.53796971148509165e+01, + y = -2.59193146099879641e+01, + z = 1.79258772950371181e-01, + vx = 2.68067772490389322e-03 * DaysPeryear, + vy = 1.62824170038242295e-03 * DaysPeryear, + vz = -9.51592254519715870e-05 * DaysPeryear, + mass = 5.15138902046611451e-05 * Solarmass, + }, + }; + + pairs = new Pair[bodies.Length * (bodies.Length - 1) / 2]; + int pi = 0; + for (int i = 0; i < bodies.Length - 1; i++) + for (int j = i + 1; j < bodies.Length; j++) + pairs[pi++] = new Pair() { bi = bodies[i], bj = bodies[j] }; + + double px = 0.0, py = 0.0, pz = 0.0; + foreach (var b in bodies) + { + px += b.vx * b.mass; py += b.vy * b.mass; pz += b.vz * b.mass; + } + var sol = bodies[0]; + sol.vx = -px / Solarmass; sol.vy = -py / Solarmass; sol.vz = -pz / Solarmass; + } + + public void Advance(double dt) + { + foreach (var p in pairs) + { + Body bi = p.bi, bj = p.bj; + double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z; + double d2 = dx * dx + dy * dy + dz * dz; + double mag = dt / (d2 * Math.Sqrt(d2)); + bi.vx -= dx * bj.mass * mag; bj.vx += dx * bi.mass * mag; + bi.vy -= dy * bj.mass * mag; bj.vy += dy * bi.mass * mag; + bi.vz -= dz * bj.mass * mag; bj.vz += dz * bi.mass * mag; + } + foreach (var b in bodies) + { + b.x += dt * b.vx; b.y += dt * b.vy; b.z += dt * b.vz; + } + } + + public double Energy() + { + double e = 0.0; + for (int i = 0; i < bodies.Length; i++) + { + var bi = bodies[i]; + e += 0.5 * bi.mass * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz); + for (int j = i + 1; j < bodies.Length; j++) + { + var bj = bodies[j]; + double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z; + e -= (bi.mass * bj.mass) / Math.Sqrt(dx * dx + dy * dy + dz * dz); + } + } + return e; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.csproj similarity index 97% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.csproj index 5d5c7f72c6df..da46bac20193 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-3.csproj @@ -28,7 +28,7 @@ - + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs deleted file mode 100644 index 60e083ad11ba..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs +++ /dev/null @@ -1,158 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Isaac Gouy, optimization and use of more C# idioms by Robert F. Tobler - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ -public class NBody -{ - public static int Main(String[] args) - { - int n = args.Length > 0 ? Int32.Parse(args[0]) : 10000; - NBodySystem bodies = new NBodySystem(); - double initialEnergy = bodies.Energy(); - Console.WriteLine("{0:f9}", initialEnergy); - for (int i = 0; i < n; i++) bodies.Advance(0.01); - double finalEnergy = bodies.Energy(); - Console.WriteLine("{0:f9}", finalEnergy); - double deltaEnergy = Math.Abs(initialEnergy - finalEnergy); - bool result = deltaEnergy < 1e-4; - Console.WriteLine("Energy {0} conserved", result ? "was" : "was not"); - return (result ? 100 : -1); - } - - [Benchmark] - public static void Bench() - { - int n = 5000000; - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - NBodySystem bodies = new NBodySystem(); - for (int i = 0; i < n; i++) bodies.Advance(0.01); - } - } - } -} - -internal class Body { public double x, y, z, vx, vy, vz, mass; } -internal class Pair { public Body bi, bj; } - -internal class NBodySystem -{ - private Body[] _bodies; - private Pair[] _pairs; - - private const double Pi = 3.141592653589793; - private const double Solarmass = 4 * Pi * Pi; - private const double DaysPeryear = 365.24; - - public NBodySystem() - { - _bodies = new Body[] { - new Body() { // Sun - mass = Solarmass, - }, - new Body() { // Jupiter - x = 4.84143144246472090e+00, - y = -1.16032004402742839e+00, - z = -1.03622044471123109e-01, - vx = 1.66007664274403694e-03 * DaysPeryear, - vy = 7.69901118419740425e-03 * DaysPeryear, - vz = -6.90460016972063023e-05 * DaysPeryear, - mass = 9.54791938424326609e-04 * Solarmass, - }, - new Body() { // Saturn - x = 8.34336671824457987e+00, - y = 4.12479856412430479e+00, - z = -4.03523417114321381e-01, - vx = -2.76742510726862411e-03 * DaysPeryear, - vy = 4.99852801234917238e-03 * DaysPeryear, - vz = 2.30417297573763929e-05 * DaysPeryear, - mass = 2.85885980666130812e-04 * Solarmass, - }, - new Body() { // Uranus - x = 1.28943695621391310e+01, - y = -1.51111514016986312e+01, - z = -2.23307578892655734e-01, - vx = 2.96460137564761618e-03 * DaysPeryear, - vy = 2.37847173959480950e-03 * DaysPeryear, - vz = -2.96589568540237556e-05 * DaysPeryear, - mass = 4.36624404335156298e-05 * Solarmass, - }, - new Body() { // Neptune - x = 1.53796971148509165e+01, - y = -2.59193146099879641e+01, - z = 1.79258772950371181e-01, - vx = 2.68067772490389322e-03 * DaysPeryear, - vy = 1.62824170038242295e-03 * DaysPeryear, - vz = -9.51592254519715870e-05 * DaysPeryear, - mass = 5.15138902046611451e-05 * Solarmass, - }, - }; - - _pairs = new Pair[_bodies.Length * (_bodies.Length - 1) / 2]; - int pi = 0; - for (int i = 0; i < _bodies.Length - 1; i++) - for (int j = i + 1; j < _bodies.Length; j++) - _pairs[pi++] = new Pair() { bi = _bodies[i], bj = _bodies[j] }; - - double px = 0.0, py = 0.0, pz = 0.0; - foreach (var b in _bodies) - { - px += b.vx * b.mass; py += b.vy * b.mass; pz += b.vz * b.mass; - } - var sol = _bodies[0]; - sol.vx = -px / Solarmass; sol.vy = -py / Solarmass; sol.vz = -pz / Solarmass; - } - - public void Advance(double dt) - { - foreach (var p in _pairs) - { - Body bi = p.bi, bj = p.bj; - double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z; - double d2 = dx * dx + dy * dy + dz * dz; - double mag = dt / (d2 * Math.Sqrt(d2)); - bi.vx -= dx * bj.mass * mag; bj.vx += dx * bi.mass * mag; - bi.vy -= dy * bj.mass * mag; bj.vy += dy * bi.mass * mag; - bi.vz -= dz * bj.mass * mag; bj.vz += dz * bi.mass * mag; - } - foreach (var b in _bodies) - { - b.x += dt * b.vx; b.y += dt * b.vy; b.z += dt * b.vz; - } - } - - public double Energy() - { - double e = 0.0; - for (int i = 0; i < _bodies.Length; i++) - { - var bi = _bodies[i]; - e += 0.5 * bi.mass * (bi.vx * bi.vx + bi.vy * bi.vy + bi.vz * bi.vz); - for (int j = i + 1; j < _bodies.Length; j++) - { - var bj = _bodies[j]; - double dx = bi.x - bj.x, dy = bi.y - bj.y, dz = bi.z - bj.z; - e -= (bi.mass * bj.mass) / Math.Sqrt(dx * dx + dy * dy + dz * dz); - } - } - return e; - } -} -} - diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs deleted file mode 100644 index 3c79a89edc8e..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pi-digits.cs +++ /dev/null @@ -1,116 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - * http://benchmarksgame.alioth.debian.org/ - * - * Port of the C code that uses GMP - * Just switched it to use C#'s BigInteger instead - * - * To compile use csc /o+ /r:System.Numerics.dll - * - * modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.Numerics; -using System.Text; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ -public class pidigits -{ -#if DEBUG - public const int Iterations = 1; -#else - public const int Iterations = 50; -#endif - - private BigInteger _acc,_den,_num; - - public pidigits() - { - _acc = BigInteger.Zero; - _den = BigInteger.One; - _num = BigInteger.One; - } - - public uint extract_digit(uint nth) - { - return (uint)((_num * nth + _acc) / _den); - } - - public void eliminate_digit(uint d) - { - _acc -= _den * d; - _acc *= 10; - _num *= 10; - } - - public void next_term(uint k) - { - uint k2 = k * 2 + 1; - _acc += _num * 2; - _acc *= k2; - _den *= k2; - _num *= k; - } - - public void Calculate(int n, bool verbose = false) - { - StringBuilder sb = new StringBuilder(20); - uint d, k, i; - for (i = k = 0; i < n;) - { - next_term(++k); - if (_num > _acc) - continue; - d = extract_digit(3); - if (d != extract_digit(4)) - continue; - sb.Append((char)('0' + d)); - if (++i % 10 == 0) - { - if (verbose) - { - Console.WriteLine("{0}\t:{1}", sb, i); - } - sb.Clear(); - } - eliminate_digit(d); - } - } - - public static int Main(String[] args) - { - int length = args.Length == 0 ? 10 : Int32.Parse(args[0]); - for (int i = 0; i < Iterations; i++) - { - pidigits p = new pidigits(); - p.Calculate(length, true); - } - return 100; - } - - [Benchmark] - public static void Bench() - { - int length = 600; - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - pidigits p = new pidigits(); - p.Calculate(length); - } - } - } - } -} -} - diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.cs new file mode 100644 index 000000000000..0f97c277d5a9 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.cs @@ -0,0 +1,160 @@ +// 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. + +// Adapted from pidigits C# .NET Core #3 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=pidigits&lang=csharpcore&id=3 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/pidigits/pidigits.csharp-3.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 +// (also best-scoring single-threaded C# .NET Core version as of 2017-09-01) +// **** Version #3 on website pinvokes to native GMP library; this has been modified to +// use .NET's System.Numerics.BigInteger type instead **** + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + * + * Port of the Java port that uses native GMP to use native GMP with C# + * contributed by Miguel de Icaza, based on the Java version, that was: + * contributed by Mike Pall + * java port by Stefan Krause +*/ +using System; +using System.Numerics; +using System.Text; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + + public class pidigits + { + BigInteger q = new BigInteger(), r = new BigInteger(), s = new BigInteger(), t = new BigInteger(); + BigInteger u = new BigInteger(), v = new BigInteger(), w = new BigInteger(); + + int i; + StringBuilder strBuf = new StringBuilder(40), lastBuf = null; + int n; + + pidigits(int n) + { + this.n = n; + } + + private void compose_r(int bq, int br, int bs, int bt) + { + u = r * bs; + r *= bq; + v = t * br; + r += v; + t *= bt; + t += u; + s *= bt; + u = q * bs; + s += u; + q *= bq; + } + + /* Compose matrix with numbers on the left. */ + private void compose_l(int bq, int br, int bs, int bt) + { + r *= bt; + u = q * br; + r += u; + u = t * bs; + t *= bt; + v = s * br; + t += v; + s *= bq; + s += u; + q *= bq; + } + + /* Extract one digit. */ + private int extract(int j) + { + u = q * j; + u += r; + v = s * j; + v += t; + w = u / v; + return (int)w; + } + + /* Print one digit. Returns 1 for the last digit. */ + private bool prdigit(int y, bool verbose) + { + strBuf.Append(y); + if (++i % 10 == 0 || i == n) + { + if (i % 10 != 0) + for (int j = 10 - (i % 10); j > 0; j--) + { strBuf.Append(" "); } + strBuf.Append("\t:"); + strBuf.Append(i); + if (verbose) Console.WriteLine(strBuf); + lastBuf = strBuf; + strBuf = new StringBuilder(40); + } + return i == n; + } + + /* Generate successive digits of PI. */ + void Run(bool verbose) + { + int k = 1; + i = 0; + q = 1; + r = 0; + s = 0; + t = 1; + for (; ; ) + { + int y = extract(3); + if (y == extract(4)) + { + if (prdigit(y, verbose)) + return; + compose_r(10, -10 * y, 0, 1); + } + else + { + compose_l(k, 4 * k + 2, 0, 2 * k + 1); + k++; + } + } + } + + public static int Main(String[] args) + { + int n = (args.Length > 0 ? Int32.Parse(args[0]) : 10); + string result = Bench(n, true).ToString(); + if (result != "3141592653\t:10") + { + return -1; + } + return 100; + } + + public static StringBuilder Bench(int n, bool verbose) + { + pidigits m = new pidigits(n); + m.Run(verbose); + return m.lastBuf; + } + } + + public class PiDigits_3 + { + [Benchmark] + [InlineData(3000, "8649423196\t:3000")] + public static void RunBench(int n, string expected) + { + StringBuilder result = null; + Benchmark.Iterate(() => result = pidigits.Bench(n, false)); + Assert.Equal(expected, result.ToString()); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.csproj new file mode 100644 index 000000000000..55a5ee7ef773 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-3.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {E37DE574-AFEC-40E8-B513-FBB09D5EFFFF} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/harness-helpers.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/harness-helpers.cs new file mode 100644 index 000000000000..25627bad5a2d --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/harness-helpers.cs @@ -0,0 +1,94 @@ +// 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. + +// Helper functionality to locate inputs and find outputs for +// regex-redux benchmark in CoreCLR test harness + +using System; +using System.IO; +using System.Text; + +namespace BenchmarksGame +{ + class TestHarnessHelpers + { + public string InputFile; + public int ExpectedLength; + + public TestHarnessHelpers(bool bigInput, [System.Runtime.CompilerServices.CallerFilePath] string csFileName = "") + { + if (bigInput) + { + InputFile = FindInputFile("regexdna-input25000.txt", csFileName); + ExpectedLength = 136381; + } + else + { + InputFile = FindInputFile("regexdna-input25.txt", csFileName); + ExpectedLength = 152; + } + } + + public string FindInputFile(string inputFile, string csFileName) + { + string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); + + if (CoreRoot == null) + { + Console.WriteLine("This benchmark requries CORE_ROOT to be set"); + return null; + } + + // The convention is that the csproj file has the same name as the cs file. + string projectName = Path.GetFileNameWithoutExtension(csFileName); + int slashIndex = projectName.LastIndexOfAny(new char[] { '/', '\\' }); + if (slashIndex != -1) + { + // csFileName was generated by the C# compiler, which may have run on + // a different host system with different path separator than the + // currently executing host, which dictates GetFileNameWithoutExtension's + // behavior... so hope that the slash here is a cross-host path separator, + // and chop of what were likely direcotires. + projectName = projectName.Substring(slashIndex + 1); + } + + // Normal testing -- input file will end up next to the assembly + // and CoreRoot points at the test overlay dir + string[] pathPartsNormal = new string[] { + CoreRoot, "..", "..", "JIT", "Performance", + "CodeQuality", "BenchmarksGame", "regex-redux", projectName, inputFile + }; + + string inputPathNormal = Path.Combine(pathPartsNormal); + + // Perf testing -- input file will end up next to the assembly + // and CoreRoot points at this directory + string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; + + string inputPathPerf = Path.Combine(pathPartsPerf); + + string inputPath = null; + + if (File.Exists(inputPathNormal)) + { + inputPath = inputPathNormal; + } + else if (File.Exists(inputPathPerf)) + { + inputPath = inputPathPerf; + } + + if (inputPath != null) + { + Console.WriteLine("Using input file {0}", inputFile); + } + else + { + throw new Exception($"Unable to find input file {inputFile}. Tried {inputPathNormal} and {inputPathPerf}; csFileName was {csFileName}, so projectName was {projectName}."); + } + + return inputPath; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.cs new file mode 100644 index 000000000000..730100284ee7 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.cs @@ -0,0 +1,131 @@ +// 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. + +// Adapted from regex-redux C# .NET Core program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=regexredux&lang=csharpcore&id=1 +// aka (as of 2017-09-01) rev 1.3 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/regexredux/regexredux.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + * + * regex-dna program contributed by Isaac Gouy + * converted from regex-dna program + * +*/ + +using System; +using System.IO; +using System.Text.RegularExpressions; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class RegexRedux_1 + { + static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + + using (var inputStream = new FileStream(helpers.InputFile, FileMode.Open)) + using (var input = new StreamReader(inputStream)) + { + if (Bench(input, true) != helpers.ExpectedLength) + { + return -1; + } + } + + return 100; + } + + [Benchmark(InnerIterationCount = 5)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + + Benchmark.Iterate(() => + { + using (var inputStream = new FileStream(helpers.InputFile, FileMode.Open)) + using (var input = new StreamReader(inputStream)) + { + Assert.Equal(helpers.ExpectedLength, Bench(input, false)); + } + }); + } + + static int Bench(TextReader inputReader, bool verbose) + { + // read FASTA sequence + String sequence = inputReader.ReadToEnd(); + int initialLength = sequence.Length; + + // remove FASTA sequence descriptions and new-lines + Regex r = new Regex(">.*\n|\n", RegexOptions.Compiled); + sequence = r.Replace(sequence, ""); + int codeLength = sequence.Length; + + + // regex match + string[] variants = { + "agggtaaa|tttaccct", + "[cgt]gggtaaa|tttaccc[acg]", + "a[act]ggtaaa|tttacc[agt]t", + "ag[act]gtaaa|tttac[agt]ct", + "agg[act]taaa|ttta[agt]cct", + "aggg[acg]aaa|ttt[cgt]ccct", + "agggt[cgt]aa|tt[acg]accct", + "agggta[cgt]a|t[acg]taccct", + "agggtaa[cgt]|[acg]ttaccct" + }; + + int count; + foreach (string v in variants) + { + count = 0; + r = new Regex(v, RegexOptions.Compiled); + + for (Match m = r.Match(sequence); m.Success; m = m.NextMatch()) count++; + if (verbose) + Console.WriteLine("{0} {1}", v, count); + } + + + // regex substitution + IUB[] codes = { + new IUB("tHa[Nt]", "<4>"), + new IUB("aND|caN|Ha[DS]|WaS", "<3>"), + new IUB("a[NSt]|BY", "<2>"), + new IUB("<[^>]*>", "|"), + new IUB("\\|[^|][^|]*\\|" , "-") + }; + + foreach (IUB iub in codes) + { + r = new Regex(iub.code, RegexOptions.Compiled); + sequence = r.Replace(sequence, iub.alternatives); + } + if (verbose) + Console.WriteLine("\n{0}\n{1}\n{2}", initialLength, codeLength, sequence.Length); + + return sequence.Length; + } + + + struct IUB + { + public string code; + public string alternatives; + + public IUB(string code, string alternatives) + { + this.code = code; + this.alternatives = alternatives; + } + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.csproj similarity index 93% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.csproj index e7b9d42bd0be..a2acf1f1fe5d 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-1.csproj @@ -5,7 +5,7 @@ Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {EFF6D8FE-2713-41B7-BF77-8DD03BADFAB6} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -30,7 +30,8 @@ - + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.cs new file mode 100644 index 000000000000..8eb5f9ed82e2 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.cs @@ -0,0 +1,123 @@ +// 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. + +// Adapted from regex-redux C# .NET Core #5 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=regexredux&lang=csharpcore&id=5 +// aka (as of 2017-09-01) rev 1.3 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/regexredux/regexredux.csharp-5.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + Regex-Redux by Josh Goldfoot + order variants by execution time by Anthony Lloyd +*/ + +using System; +using System.IO; +using System.Threading.Tasks; +using System.Text.RegularExpressions; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class RegexRedux_5 + { + static Regex regex(string re) + { + // Not compiled on .Net Core, hence poor benchmark results. + return new Regex(re, RegexOptions.Compiled); + } + + static string regexCount(string s, string r) + { + int c = 0; + var m = regex(r).Match(s); + while (m.Success) { c++; m = m.NextMatch(); } + return r + " " + c; + } + + public static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + + using (var inputStream = new FileStream(helpers.InputFile, FileMode.Open)) + using (var input = new StreamReader(inputStream)) + { + if (Bench(input, true) != helpers.ExpectedLength) + { + return -1; + } + } + + return 100; + } + + [Benchmark(InnerIterationCount = 14)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + + Benchmark.Iterate(() => + { + using (var inputStream = new FileStream(helpers.InputFile, FileMode.Open)) + using (var input = new StreamReader(inputStream)) + { + Assert.Equal(helpers.ExpectedLength, Bench(input, false)); + } + }); + } + + static int Bench(TextReader inputReader, bool verbose) + { + var sequences = inputReader.ReadToEnd(); + var initialLength = sequences.Length; + sequences = Regex.Replace(sequences, ">.*\n|\n", ""); + + var magicTask = Task.Run(() => + { + var newseq = regex("tHa[Nt]").Replace(sequences, "<4>"); + newseq = regex("aND|caN|Ha[DS]|WaS").Replace(newseq, "<3>"); + newseq = regex("a[NSt]|BY").Replace(newseq, "<2>"); + newseq = regex("<[^>]*>").Replace(newseq, "|"); + newseq = regex("\\|[^|][^|]*\\|").Replace(newseq, "-"); + return newseq.Length; + }); + + var variant2 = Task.Run(() => regexCount(sequences, "[cgt]gggtaaa|tttaccc[acg]")); + var variant3 = Task.Run(() => regexCount(sequences, "a[act]ggtaaa|tttacc[agt]t")); + var variant7 = Task.Run(() => regexCount(sequences, "agggt[cgt]aa|tt[acg]accct")); + var variant6 = Task.Run(() => regexCount(sequences, "aggg[acg]aaa|ttt[cgt]ccct")); + var variant4 = Task.Run(() => regexCount(sequences, "ag[act]gtaaa|tttac[agt]ct")); + var variant5 = Task.Run(() => regexCount(sequences, "agg[act]taaa|ttta[agt]cct")); + var variant1 = Task.Run(() => regexCount(sequences, "agggtaaa|tttaccct")); + var variant9 = Task.Run(() => regexCount(sequences, "agggtaa[cgt]|[acg]ttaccct")); + var variant8 = Task.Run(() => regexCount(sequences, "agggta[cgt]a|t[acg]taccct")); + + if (verbose) + { + Console.Out.WriteLineAsync(variant1.Result); + Console.Out.WriteLineAsync(variant2.Result); + Console.Out.WriteLineAsync(variant3.Result); + Console.Out.WriteLineAsync(variant4.Result); + Console.Out.WriteLineAsync(variant5.Result); + Console.Out.WriteLineAsync(variant6.Result); + Console.Out.WriteLineAsync(variant7.Result); + Console.Out.WriteLineAsync(variant8.Result); + Console.Out.WriteLineAsync(variant9.Result); + Console.Out.WriteLineAsync("\n" + initialLength + "\n" + sequences.Length); + Console.Out.WriteLineAsync(magicTask.Result.ToString()); + } + else + { + Task.WaitAll(variant1, variant2, variant3, variant4, variant5, variant6, variant7, variant8, variant9); + } + + return magicTask.Result; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.csproj new file mode 100644 index 000000000000..cd45a0937c15 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-5.csproj @@ -0,0 +1,49 @@ + + + + + Debug + AnyCPU + 2.0 + {FCEF2E71-7E24-4306-9CCA-56BD251FB66E} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + Always + + + Always + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25.txt b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25.txt similarity index 100% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25.txt rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25.txt diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25000.txt b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25000.txt similarity index 100% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-input25000.txt rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regexdna-input25000.txt diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csharp-6.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csharp-6.cs deleted file mode 100644 index 882bfd23f975..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna.csharp-6.cs +++ /dev/null @@ -1,229 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - * - * contributed by Jimmy Tang - * - * modified for use with xunit-performance - */ - -using Microsoft.Xunit.Performance; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.RegularExpressions; -using System.Threading; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ - -public static class Regexdna -{ - -#if DEBUG - const bool Verbose = true; - const int Iterations = 1; - const string InputFile = "regexdna-input25.txt"; -#else - const bool Verbose = false; - const int Iterations = 6; - const string InputFile = "regexdna-input25000.txt"; -#endif - - static string FindInput(string s) - { - string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); - - if (CoreRoot == null) - { - Console.WriteLine("This benchmark requries CORE_ROOT to be set"); - return null; - } - - string inputFile = s ?? InputFile; - - // Normal testing -- input file will end up next to the assembly - // and CoreRoot points at the test overlay dir - string[] pathPartsNormal = new string[] { - CoreRoot, "..", "..", "JIT", "Performance", - "CodeQuality", "BenchmarksGame", "regexdna", "regexdna", inputFile - }; - - string inputPathNormal = Path.Combine(pathPartsNormal); - - // Perf testing -- input file will end up next to the assembly - // and CoreRoot points at this directory - string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; - - string inputPathPerf = Path.Combine(pathPartsPerf); - - string inputPath = null; - - if (File.Exists(inputPathNormal)) - { - inputPath = inputPathNormal; - } - else if (File.Exists(inputPathPerf)) - { - inputPath = inputPathPerf; - } - - if (inputPath != null) - { - Console.WriteLine("Using input file {0}", inputPath); - } - else - { - Console.WriteLine("Unable to find input file {0}", inputFile); - } - - return inputPath; - } - - public static int Main(string[] args) - { - string inputFile = InputFile; - int iterations = Iterations; - bool verbose = Verbose; - - for (int i = 0; i < args.Length; i++) - { - if (args[i] == "-v") - { - verbose = true; - } - else if (args[i] == "-q") - { - verbose = false; - } - else if (args[i] == "-i") - { - i++; - - if (i < args.Length) - { - Int32.TryParse(args[i], out iterations); - } - } - else - { - inputFile = args[i]; - } - } - - string fullInputFile = FindInput(inputFile); - - if (fullInputFile == null) - { - Console.WriteLine("unable to find input"); - return -1; - } - - if (iterations != Iterations) - { - Console.WriteLine("Running {0} iterations", iterations); - } - - using (var r = File.OpenText(fullInputFile)) - { - string sequence = r.ReadToEnd(); - - // Warmup - - BenchInner(verbose, sequence); - - Stopwatch sw = Stopwatch.StartNew(); - for (int j = 0; j < iterations; j++) - { - BenchInner(verbose, sequence); - } - sw.Stop(); - - Console.WriteLine("regexdna [{0} iters]: {1}ms", iterations, sw.ElapsedMilliseconds); - } - - return 100; - } - - static void BenchInner(bool verbose, string sequence) - { - int initialLength = sequence.Length; - - sequence = Regex.Replace(sequence, ">.*\n|\n", ""); - int codeLength = sequence.Length; - - string[] variants = { - "agggtaaa|tttaccct" - ,"[cgt]gggtaaa|tttaccc[acg]" - ,"a[act]ggtaaa|tttacc[agt]t" - ,"ag[act]gtaaa|tttac[agt]ct" - ,"agg[act]taaa|ttta[agt]cct" - ,"aggg[acg]aaa|ttt[cgt]ccct" - ,"agggt[cgt]aa|tt[acg]accct" - ,"agggta[cgt]a|t[acg]taccct" - ,"agggtaa[cgt]|[acg]ttaccct" - }; - - var flags = variants.Select((v, i) => { - var flag = new ManualResetEvent(false); - ThreadPool.QueueUserWorkItem(x => { - variants[i] += " " + Regex.Matches(sequence, v).Count; - flag.Set(); - }); - return flag; - }); - WaitHandle.WaitAll(flags.ToArray()); - if (verbose) - { - Console.WriteLine(string.Join("\n", variants)); - } - - var dict = new Dictionary { - {"B", "(c|g|t)"}, {"D", "(a|g|t)"}, {"H", "(a|c|t)"}, {"K", "(g|t)"}, - {"M", "(a|c)"}, {"N", "(a|c|g|t)"}, {"R", "(a|g)"}, {"S", "(c|g)"}, - {"V", "(a|c|g)"}, {"W", "(a|t)"}, {"Y", "(c|t)"} - }; - - sequence = new Regex("[WYKMSRBDVHN]").Replace(sequence, m => dict[m.Value]); - - if (verbose) - { - Console.WriteLine("\n{0}\n{1}\n{2}", initialLength, codeLength, sequence.Length); - } - } - - [Benchmark] - public static void Bench() - { - string fullInputFile = FindInput(InputFile); - - if (fullInputFile == null) - { - throw new Exception("unable to find input"); - } - - using (var r = File.OpenText(fullInputFile)) - { - string sequence = r.ReadToEnd(); - - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - BenchInner(false, sequence); - } - } - } - } - } -} - -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs deleted file mode 100644 index bca63bd00e21..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs +++ /dev/null @@ -1,249 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Robert F. Tobler to process large blocks of byte arrays - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ - -public static class Revcomp -{ - -#if DEBUG - const int Iterations = 1; - const string InputFile = "revcomp-input25.txt"; -#else - const int Iterations = 800; - const string InputFile = "revcomp-input25000.txt"; -#endif - - struct Block { - public byte[] Data; public int Count; - public int Read(BinaryReader r) { - Data = r.ReadBytes(16384); Count++; return Data.Length; - } - public Index IndexOf(byte b, int o) { - return new Index { Block = Count, Pos = Array.IndexOf(Data, b, o) }; - } - } - - struct Index { - public int Block; public int Pos; - public static readonly Index None = new Index { Block = -1, Pos = -1 }; - public bool InBlock(Block b) { return Block == b.Count; } - } - - const byte Gt = (byte)'>'; - const byte Lf = (byte)'\n'; - - static string FindInput(string s) - { - string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); - - if (CoreRoot == null) - { - Console.WriteLine("This benchmark requries CORE_ROOT to be set"); - return null; - } - - string inputFile = s ?? InputFile; - - // Normal testing -- input file will end up next to the assembly - // and CoreRoot points at the test overlay dir - string[] pathPartsNormal = new string[] { - CoreRoot, "..", "..", "JIT", "Performance", - "CodeQuality", "BenchmarksGame", "revcomp", "revcomp", inputFile - }; - - string inputPathNormal = Path.Combine(pathPartsNormal); - - // Perf testing -- input file will end up next to the assembly - // and CoreRoot points at this directory - string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; - - string inputPathPerf = Path.Combine(pathPartsPerf); - - string inputPath = null; - - if (File.Exists(inputPathNormal)) - { - inputPath = inputPathNormal; - } - else if (File.Exists(inputPathPerf)) - { - inputPath = inputPathPerf; - } - - if (inputPath != null) - { - Console.WriteLine("Using input file {0}", inputPath); - } - else - { - Console.WriteLine("Unable to find input file {0}", inputFile); - } - - return inputPath; - } - - static int Main(string[] args) - { - bool verbose = false; - string inputFile = InputFile; - int iterations = Iterations; - - for (int i = 0; i < args.Length; i++) - { - if (args[i] == "-v") - { - verbose = true; - } - if (args[i] == "-i") - { - i++; - - if (i < args.Length) - { - Int32.TryParse(args[i], out iterations); - } - } - else - { - inputFile = args[i]; - } - } - - string fullInputFile = FindInput(inputFile); - - if (fullInputFile == null) - { - return -1; - } - - if (iterations != Iterations) - { - Console.WriteLine("Running {0} iterations", iterations); - } - - // Warmup - BenchInner(false, fullInputFile); - - Stopwatch sw = Stopwatch.StartNew(); - for (int j = 0; j < iterations; j++) - { - BenchInner(verbose, fullInputFile); - } - sw.Stop(); - Console.WriteLine("revcomp [{0} iters]: {1}ms", iterations, sw.ElapsedMilliseconds); - - return 100; - } - - static void BenchInner(bool doOutput, string inputFile) - { - InitComplements(); - var seq = new List(); - var b = new Block { Count = -1 }; - Index line = Index.None, start = Index.None, end = Index.None; - using (var r = new BinaryReader(File.OpenRead(inputFile))) { - using (var w = doOutput ? Console.OpenStandardOutput() : Stream.Null) { - while (b.Read(r) > 0) { - seq.Add(b.Data); - if (line.Pos < 0) line = b.IndexOf(Gt, 0); - while (line.Pos >= 0) { - if (start.Pos < 0) { - var off = line.InBlock(b) ? line.Pos : 0; - start = b.IndexOf(Lf, off); - if (start.Pos < 0) { - w.Write(b.Data, off, b.Data.Length - off); - seq.Clear(); break; - } - w.Write(b.Data, off, start.Pos + 1 - off); - } - if (end.Pos < 0) { - end = b.IndexOf(Gt, start.InBlock(b) ? start.Pos : 0); - if (end.Pos < 0) break; - } - w.Reverse(start.Pos, end.Pos, seq); - if (seq.Count > 1) seq.RemoveRange(0, seq.Count - 1); - line = end; end = Index.None; start = Index.None; - } - } - if (start.Pos >= 0 && end.Pos < 0) - w.Reverse(start.Pos, seq[seq.Count -1].Length, seq); - } - } - } - - const string Seq = "ABCDGHKMRTVYabcdghkmrtvy"; - const string Rev = "TVGHCDMKYABRTVGHCDMKYABR"; - static byte[] comp = new byte[256]; - - static void InitComplements() { - for (byte i = 0; i < 255; i++) comp[i] = i; - for (int i = 0; i < Seq.Length; i++) - comp[(byte)Seq[i]] = (byte)Rev[i]; - comp[Lf] = 0; comp[(byte)' '] = 0; - } - - const int LineLen = 61; - const int BufSize = LineLen * 269; - static byte[] buf = new byte[BufSize]; - - static void Reverse(this Stream w, int si, int ei, List bl) { - int bi = 0, line = LineLen - 1; - for (int ri = bl.Count-1; ri >= 0; ri--) { - var b = bl[ri]; int off = ri == 0 ? si : 0; - for (int i = (ri == bl.Count-1 ? ei : b.Length)-1; i >= off; i--) { - var c = comp[b[i]]; if (c > 0) buf[bi++] = c; - if (bi == line) { - buf[bi++] = Lf; line += LineLen; - if (bi == BufSize) { - w.Write(buf, 0, BufSize); bi = 0; line = LineLen - 1; - } - } - } - } - if (bi > 0) { - if (buf[bi-1] != Lf) buf[bi++] = Lf; w.Write(buf, 0, bi); - } - } - - [Benchmark] - public static void Bench() - { - string inputFile = FindInput(InputFile); - - if (inputFile == null) - { - throw new Exception("unable to find input"); - } - - foreach (var iteration in Benchmark.Iterations) - { - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - BenchInner(false, inputFile); - } - } - } - } -} - -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/harness-helpers.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/harness-helpers.cs new file mode 100644 index 000000000000..c494982cc9a7 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/harness-helpers.cs @@ -0,0 +1,97 @@ +// 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. + +// Helper functionality to locate inputs and find outputs for +// reverse-complement benchmark in CoreCLR test harness + +using System; +using System.IO; +using System.Text; + +namespace BenchmarksGame +{ + class TestHarnessHelpers + { + public string InputFile; + public int FileLength; + public string CheckSum; + + public TestHarnessHelpers(bool bigInput, [System.Runtime.CompilerServices.CallerFilePath] string csFileName = "") + { + if (bigInput) + { + InputFile = FindInputFile("revcomp-input25000.txt", csFileName); + FileLength = 254245; + CheckSum = "61-A4-CC-6D-15-8D-26-77-88-93-4F-E2-29-A2-8D-FB"; + } + else + { + InputFile = FindInputFile("revcomp-input25.txt", csFileName); + FileLength = 333; + CheckSum = "62-45-8E-09-2E-89-A0-69-8C-17-F5-D8-C7-63-5B-50"; + } + } + + public string FindInputFile(string inputFile, string csFileName) + { + string CoreRoot = System.Environment.GetEnvironmentVariable("CORE_ROOT"); + + if (CoreRoot == null) + { + Console.WriteLine("This benchmark requries CORE_ROOT to be set"); + return null; + } + + // The convention is that the csproj file has the same name as the cs file. + string projectName = Path.GetFileNameWithoutExtension(csFileName); + int slashIndex = projectName.LastIndexOfAny(new char[] { '/', '\\' }); + if (slashIndex != -1) + { + // csFileName was generated by the C# compiler, which may have run on + // a different host system with different path separator than the + // currently executing host, which dictates GetFileNameWithoutExtension's + // behavior... so hope that the slash here is a cross-host path separator, + // and chop of what were likely direcotires. + projectName = projectName.Substring(slashIndex + 1); + } + + // Normal testing -- input file will end up next to the assembly + // and CoreRoot points at the test overlay dir + string[] pathPartsNormal = new string[] { + CoreRoot, "..", "..", "JIT", "Performance", + "CodeQuality", "BenchmarksGame", "reverse-complement", projectName, inputFile + }; + + string inputPathNormal = Path.Combine(pathPartsNormal); + + // Perf testing -- input file will end up next to the assembly + // and CoreRoot points at this directory + string[] pathPartsPerf = new string[] { CoreRoot, inputFile }; + + string inputPathPerf = Path.Combine(pathPartsPerf); + + string inputPath = null; + + if (File.Exists(inputPathNormal)) + { + inputPath = inputPathNormal; + } + else if (File.Exists(inputPathPerf)) + { + inputPath = inputPathPerf; + } + + if (inputPath != null) + { + Console.WriteLine("Using input file {0}", inputFile); + } + else + { + throw new Exception($"Unable to find input file {inputFile}. Tried {inputPathNormal} and {inputPathPerf}; csFileName was {csFileName}, so projectName was {projectName}."); + } + + return inputPath; + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25.txt b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25.txt similarity index 100% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25.txt rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25.txt diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25000.txt b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25000.txt similarity index 100% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25000.txt rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25000.txt diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.cs new file mode 100644 index 000000000000..902aee39ce68 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.cs @@ -0,0 +1,180 @@ +// 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. + +// Adapted from reverse-complement C# .NET Core program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=csharpcore&id=1 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/revcomp/revcomp.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Robert F. Tobler to process large blocks of byte arrays +*/ + +using System; +using System.IO; +using System.Collections.Generic; +using System.Security.Cryptography; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public static class ReverseComplement_1 + { + struct Block + { + public byte[] Data; public int Count; + public int Read(BinaryReader r) + { + Data = r.ReadBytes(16384); Count++; return Data.Length; + } + public Index IndexOf(byte b, int o) + { + return new Index { Block = Count, Pos = Array.IndexOf(Data, b, o) }; + } + } + + struct Index + { + public int Block; public int Pos; + public static readonly Index None = new Index { Block = -1, Pos = -1 }; + public bool InBlock(Block b) { return Block == b.Count; } + } + + const byte Gt = (byte)'>'; + const byte Lf = (byte)'\n'; + + static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + var outBytes = new byte[helpers.FileLength]; + using (var input = new FileStream(helpers.InputFile, FileMode.Open)) + using (var output = new MemoryStream(outBytes)) + { + Bench(input, output); + } + Console.WriteLine(System.Text.Encoding.UTF8.GetString(outBytes)); + if (!MatchesChecksum(outBytes, helpers.CheckSum)) + { + return -1; + } + return 100; + } + + [Benchmark(InnerIterationCount = 1500)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + var outBytes = new byte[helpers.FileLength]; + + Benchmark.Iterate(() => + { + using (var input = new FileStream(helpers.InputFile, FileMode.Open)) + using (var output = new MemoryStream(outBytes)) + { + Bench(input, output); + } + }); + + Assert.True(MatchesChecksum(outBytes, helpers.CheckSum)); + } + + static bool MatchesChecksum(byte[] bytes, string checksum) + { + using (var md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(bytes); + return (checksum == BitConverter.ToString(hash)); + } + } + + static void Bench(Stream input, Stream output) + { + InitComplements(); + var seq = new List(); + var b = new Block { Count = -1 }; + Index line = Index.None, start = Index.None, end = Index.None; + using (var r = new BinaryReader(input)) + { + using (var w = output) + { + while (b.Read(r) > 0) + { + seq.Add(b.Data); + if (line.Pos < 0) line = b.IndexOf(Gt, 0); + while (line.Pos >= 0) + { + if (start.Pos < 0) + { + var off = line.InBlock(b) ? line.Pos : 0; + start = b.IndexOf(Lf, off); + if (start.Pos < 0) + { + w.Write(b.Data, off, b.Data.Length - off); + seq.Clear(); break; + } + w.Write(b.Data, off, start.Pos + 1 - off); + } + if (end.Pos < 0) + { + end = b.IndexOf(Gt, start.InBlock(b) ? start.Pos : 0); + if (end.Pos < 0) break; + } + w.Reverse(start.Pos, end.Pos, seq); + if (seq.Count > 1) seq.RemoveRange(0, seq.Count - 1); + line = end; end = Index.None; start = Index.None; + } + } + if (start.Pos >= 0 && end.Pos < 0) + w.Reverse(start.Pos, seq[seq.Count - 1].Length, seq); + } + } + } + + const string Seq = "ABCDGHKMRTVYabcdghkmrtvy"; + const string Rev = "TVGHCDMKYABRTVGHCDMKYABR"; + static byte[] comp = new byte[256]; + + static void InitComplements() + { + for (byte i = 0; i < 255; i++) comp[i] = i; + for (int i = 0; i < Seq.Length; i++) + comp[(byte)Seq[i]] = (byte)Rev[i]; + comp[Lf] = 0; comp[(byte)' '] = 0; + } + + const int LineLen = 61; + const int BufSize = LineLen * 269; + static byte[] buf = new byte[BufSize]; + + static void Reverse(this Stream w, int si, int ei, List bl) + { + int bi = 0, line = LineLen - 1; + for (int ri = bl.Count - 1; ri >= 0; ri--) + { + var b = bl[ri]; int off = ri == 0 ? si : 0; + for (int i = (ri == bl.Count - 1 ? ei : b.Length) - 1; i >= off; i--) + { + var c = comp[b[i]]; if (c > 0) buf[bi++] = c; + if (bi == line) + { + buf[bi++] = Lf; line += LineLen; + if (bi == BufSize) + { + w.Write(buf, 0, BufSize); bi = 0; line = LineLen - 1; + } + } + } + } + if (bi > 0) + { + if (buf[bi - 1] != Lf) buf[bi++] = Lf; w.Write(buf, 0, bi); + } + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.csproj similarity index 93% rename from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csproj rename to tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.csproj index 00789ed3a576..5e0c567553a3 100644 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csproj +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-1.csproj @@ -5,7 +5,7 @@ Debug AnyCPU 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} + {D10015D3-6A09-400C-8CF6-9F50BEED71D2} Exe {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ..\..\ @@ -30,7 +30,8 @@ - + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.cs new file mode 100644 index 000000000000..70d84d4f90f3 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.cs @@ -0,0 +1,290 @@ +// 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. + +// Adapted from reverse-complement C# .NET Core #6 +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=csharpcore&id=6 +// aka (as of 2017-09-01) rev 1.4 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/revcomp/revcomp.csharp-6.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + Contributed by Peperud + Modified to reduce memory use by Anthony Lloyd +*/ + +using System; +using System.IO; +using System.Collections.Generic; +using System.Collections.Concurrent; +using System.Security.Cryptography; +using System.Threading; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + class RevCompSequence + { + public List Pages; + public int StartHeader, EndExclusive; + public Thread ReverseThread; + } + + public static class ReverseComplement_6 + { + const int READER_BUFFER_SIZE = 1024 * 1024; + const byte LF = 10, GT = (byte)'>', SP = 32; + static BlockingCollection readQue; + static BlockingCollection writeQue; + static byte[] map; + + static int read(Stream stream, byte[] buffer, int offset, int count) + { + var bytesRead = stream.Read(buffer, offset, count); + return bytesRead == count ? offset + count + : bytesRead == 0 ? offset + : read(stream, buffer, offset + bytesRead, count - bytesRead); + } + static Stream ReaderStream; + static void Reader() + { + using (var stream = ReaderStream) + { + int bytesRead; + do + { + var buffer = new byte[READER_BUFFER_SIZE]; + bytesRead = read(stream, buffer, 0, READER_BUFFER_SIZE); + readQue.Add(buffer); + } while (bytesRead == READER_BUFFER_SIZE); + readQue.CompleteAdding(); + } + } + + static bool tryTake(BlockingCollection q, out T t) where T : class + { + t = null; + var wait = new SpinWait(); + while (!q.IsCompleted && !q.TryTake(out t)) wait.SpinOnce(); + return t != null; + } + + static void Grouper() + { + // Set up complements map + map = new byte[256]; + for (byte b = 0; b < 255; b++) map[b] = b; + map[(byte)'A'] = (byte)'T'; + map[(byte)'B'] = (byte)'V'; + map[(byte)'C'] = (byte)'G'; + map[(byte)'D'] = (byte)'H'; + map[(byte)'G'] = (byte)'C'; + map[(byte)'H'] = (byte)'D'; + map[(byte)'K'] = (byte)'M'; + map[(byte)'M'] = (byte)'K'; + map[(byte)'R'] = (byte)'Y'; + map[(byte)'T'] = (byte)'A'; + map[(byte)'V'] = (byte)'B'; + map[(byte)'Y'] = (byte)'R'; + map[(byte)'a'] = (byte)'T'; + map[(byte)'b'] = (byte)'V'; + map[(byte)'c'] = (byte)'G'; + map[(byte)'d'] = (byte)'H'; + map[(byte)'g'] = (byte)'C'; + map[(byte)'h'] = (byte)'D'; + map[(byte)'k'] = (byte)'M'; + map[(byte)'m'] = (byte)'K'; + map[(byte)'r'] = (byte)'Y'; + map[(byte)'t'] = (byte)'A'; + map[(byte)'v'] = (byte)'B'; + map[(byte)'y'] = (byte)'R'; + + var startHeader = 0; + var i = 0; + bool afterFirst = false; + var data = new List(); + byte[] bytes; + while (tryTake(readQue, out bytes)) + { + data.Add(bytes); + while ((i = Array.IndexOf(bytes, GT, i + 1)) != -1) + { + var sequence = new RevCompSequence + { + Pages = data, + StartHeader = startHeader, + EndExclusive = i + }; + if (afterFirst) + (sequence.ReverseThread = new Thread(() => Reverse(sequence))).Start(); + else + afterFirst = true; + writeQue.Add(sequence); + startHeader = i; + data = new List { bytes }; + } + } + i = Array.IndexOf(data[data.Count - 1], 0, 0); + var lastSequence = new RevCompSequence + { + Pages = data, + StartHeader = startHeader, + EndExclusive = i == -1 ? data[data.Count - 1].Length : i + }; + Reverse(lastSequence); + writeQue.Add(lastSequence); + writeQue.CompleteAdding(); + } + + static void Reverse(RevCompSequence sequence) + { + var startPageId = 0; + var startBytes = sequence.Pages[0]; + var startIndex = sequence.StartHeader; + + // Skip header line + while ((startIndex = Array.IndexOf(startBytes, LF, startIndex)) == -1) + { + startBytes = sequence.Pages[++startPageId]; + startIndex = 0; + } + + var endPageId = sequence.Pages.Count - 1; + var endIndex = sequence.EndExclusive - 1; + if (endIndex == -1) endIndex = sequence.Pages[--endPageId].Length - 1; + var endBytes = sequence.Pages[endPageId]; + + // Swap in place across pages + do + { + var startByte = startBytes[startIndex]; + if (startByte < SP) + { + if (++startIndex == startBytes.Length) + { + startBytes = sequence.Pages[++startPageId]; + startIndex = 0; + } + if (startIndex == endIndex && startPageId == endPageId) break; + startByte = startBytes[startIndex]; + } + var endByte = endBytes[endIndex]; + if (endByte < SP) + { + if (--endIndex == -1) + { + endBytes = sequence.Pages[--endPageId]; + endIndex = endBytes.Length - 1; + } + if (startIndex == endIndex && startPageId == endPageId) break; + endByte = endBytes[endIndex]; + } + + startBytes[startIndex] = map[endByte]; + endBytes[endIndex] = map[startByte]; + + if (++startIndex == startBytes.Length) + { + startBytes = sequence.Pages[++startPageId]; + startIndex = 0; + } + if (--endIndex == -1) + { + endBytes = sequence.Pages[--endPageId]; + endIndex = endBytes.Length - 1; + } + } while (startPageId < endPageId || (startPageId == endPageId && startIndex < endIndex)); + if (startIndex == endIndex) startBytes[startIndex] = map[startBytes[startIndex]]; + } + + static Stream WriterStream; + static void Writer() + { + using (var stream = WriterStream) + { + bool first = true; + RevCompSequence sequence; + while (tryTake(writeQue, out sequence)) + { + var startIndex = sequence.StartHeader; + var pages = sequence.Pages; + if (first) + { + Reverse(sequence); + first = false; + } + else + { + sequence.ReverseThread?.Join(); + } + for (int i = 0; i < pages.Count - 1; i++) + { + var bytes = pages[i]; + stream.Write(bytes, startIndex, bytes.Length - startIndex); + startIndex = 0; + } + stream.Write(pages[pages.Count - 1], startIndex, sequence.EndExclusive - startIndex); + } + } + } + + static int Main(string[] args) + { + var helpers = new TestHarnessHelpers(bigInput: false); + var outBytes = new byte[helpers.FileLength]; + using (var input = new FileStream(helpers.InputFile, FileMode.Open)) + using (var output = new MemoryStream(outBytes)) + { + Bench(input, output); + } + Console.WriteLine(System.Text.Encoding.UTF8.GetString(outBytes)); + if (!MatchesChecksum(outBytes, helpers.CheckSum)) + { + return -1; + } + return 100; + } + + [Benchmark(InnerIterationCount = 33)] + public static void RunBench() + { + var helpers = new TestHarnessHelpers(bigInput: true); + var outBytes = new byte[helpers.FileLength]; + + Benchmark.Iterate(() => + { + var input = new FileStream(helpers.InputFile, FileMode.Open); + var output = new MemoryStream(outBytes); + { + Bench(input, output); + } + }); + + Assert.True(MatchesChecksum(outBytes, helpers.CheckSum)); + } + + static bool MatchesChecksum(byte[] bytes, string checksum) + { + using (var md5 = MD5.Create()) + { + byte[] hash = md5.ComputeHash(bytes); + return (checksum == BitConverter.ToString(hash)); + } + } + + static void Bench(Stream input, Stream output) + { + readQue = new BlockingCollection(); + writeQue = new BlockingCollection(); + ReaderStream = input; + WriterStream = output; + new Thread(Reader).Start(); + new Thread(Grouper).Start(); + Writer(); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.csproj new file mode 100644 index 000000000000..b1be51cf1268 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-6.csproj @@ -0,0 +1,49 @@ + + + + + Debug + AnyCPU + 2.0 + {9449A6C4-69BD-496B-83AD-55046F464950} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + Always + + + Always + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.cs new file mode 100644 index 000000000000..117c818673f6 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.cs @@ -0,0 +1,115 @@ +// 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. + +// Adapted from spectral-norm C# .NET Core program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=spectralnorm&lang=csharpcore&id=1 +// aka (as of 2017-09-01) rev 1.2 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/spectralnorm/spectralnorm.csharp?root=benchmarksgame&view=log +// Best-scoring single-threaded C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy +*/ + +using System; +using System.Runtime.CompilerServices; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class SpectralNorm_1 + { + public static int Main(String[] args) + { + int n = 100; + if (args.Length > 0) n = Int32.Parse(args[0]); + + double norm = new SpectralNorm_1().Bench(n); + Console.WriteLine("{0:f9}", norm); + + double expected = 1.274219991; + bool result = Math.Abs(norm - expected) < 1e-4; + return (result ? 100 : -1); + } + + [Benchmark(InnerIterationCount = 700)] + public static void RunBench() + { + var obj = new SpectralNorm_1(); + double norm = 0.0; + Benchmark.Iterate(() => { norm = obj.Bench(100); }); + + double expected = 1.274219991; + Assert.True(Math.Abs(norm - expected) < 1e-4); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + double Bench(int n) + { + // create unit vector + double[] u = new double[n]; + for (int i = 0; i < n; i++) u[i] = 1; + + // 20 steps of the power method + double[] v = new double[n]; + for (int i = 0; i < n; i++) v[i] = 0; + + for (int i = 0; i < 10; i++) + { + MultiplyAtAv(n, u, v); + MultiplyAtAv(n, v, u); + } + + // B=AtA A multiplied by A transposed + // v.Bv /(v.v) eigenvalue of v + double vBv = 0, vv = 0; + for (int i = 0; i < n; i++) + { + vBv += u[i] * v[i]; + vv += v[i] * v[i]; + } + + return Math.Sqrt(vBv / vv); + } + + + /* return element i,j of infinite matrix A */ + double A(int i, int j) + { + return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1); + } + + /* multiply vector v by matrix A */ + void MultiplyAv(int n, double[] v, double[] Av) + { + for (int i = 0; i < n; i++) + { + Av[i] = 0; + for (int j = 0; j < n; j++) Av[i] += A(i, j) * v[j]; + } + } + + /* multiply vector v by matrix A transposed */ + void MultiplyAtv(int n, double[] v, double[] Atv) + { + for (int i = 0; i < n; i++) + { + Atv[i] = 0; + for (int j = 0; j < n; j++) Atv[i] += A(j, i) * v[j]; + } + } + + /* multiply vector v by matrix A and then by matrix A transposed */ + void MultiplyAtAv(int n, double[] v, double[] AtAv) + { + double[] u = new double[n]; + MultiplyAv(n, v, u); + MultiplyAtv(n, u, AtAv); + } + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.csproj new file mode 100644 index 000000000000..6aa7d71500d5 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-1.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {2FA952B1-A5C1-435D-918F-F3750714FB92} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.cs new file mode 100644 index 000000000000..4a1cf8550702 --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.cs @@ -0,0 +1,175 @@ +// 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. + +// Adapted from spectral-norm C# .NET Core #3 program +// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=spectralnorm&lang=csharpcore&id=3 +// aka (as of 2017-09-01) rev 1.1 of https://alioth.debian.org/scm/viewvc.php/benchmarksgame/bench/spectralnorm/spectralnorm.csharp-3.csharp?root=benchmarksgame&view=log +// Best-scoring C# .NET Core version as of 2017-09-01 + +/* The Computer Language Benchmarks Game + http://benchmarksgame.alioth.debian.org/ + + contributed by Isaac Gouy + modified by Josh Goldfoot, based on the Java version by The Anh Tran +*/ + +using System; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Xunit.Performance; +using Xunit; + +[assembly: OptimizeForBenchmarks] + +namespace BenchmarksGame +{ + public class SpectralNorm_3 + { + public static int Main(String[] args) + { + int n = 100; + if (args.Length > 0) n = Int32.Parse(args[0]); + + double norm = Bench(n); + Console.WriteLine("{0:f9}", norm); + + double expected = 1.274219991; + bool result = Math.Abs(norm - expected) < 1e-4; + return (result ? 100 : -1); + } + + [Benchmark(InnerIterationCount = 1400)] + public static void RunBench() + { + double norm = 0.0; + Benchmark.Iterate(() => { norm = Bench(100); }); + + double expected = 1.274219991; + Assert.True(Math.Abs(norm - expected) < 1e-4); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static double Bench(int n) + { + double[] u = new double[n]; + double[] v = new double[n]; + double[] tmp = new double[n]; + + // create unit vector + for (int i = 0; i < n; i++) + u[i] = 1.0; + + int nthread = Environment.ProcessorCount; + int chunk = n / nthread; + var barrier = new Barrier(nthread); + Approximate[] ap = new Approximate[nthread]; + + for (int i = 0; i < nthread; i++) + { + int r1 = i * chunk; + int r2 = (i < (nthread - 1)) ? r1 + chunk : n; + ap[i] = new Approximate(u, v, tmp, r1, r2, barrier); + } + + double vBv = 0, vv = 0; + for (int i = 0; i < nthread; i++) + { + ap[i].t.Wait(); + vBv += ap[i].m_vBv; + vv += ap[i].m_vv; + } + + return Math.Sqrt(vBv / vv); + } + + } + + public class Approximate + { + private Barrier barrier; + public Task t; + + private double[] _u; + private double[] _v; + private double[] _tmp; + + private int range_begin, range_end; + public double m_vBv, m_vv; + + public Approximate(double[] u, double[] v, double[] tmp, int rbegin, int rend, Barrier b) + { + m_vBv = 0; + m_vv = 0; + _u = u; + _v = v; + _tmp = tmp; + range_begin = rbegin; + range_end = rend; + barrier = b; + t = Task.Run(() => run()); + } + + private void run() + { + // 20 steps of the power method + for (int i = 0; i < 10; i++) + { + MultiplyAtAv(_u, _tmp, _v); + MultiplyAtAv(_v, _tmp, _u); + } + + for (int i = range_begin; i < range_end; i++) + { + m_vBv += _u[i] * _v[i]; + m_vv += _v[i] * _v[i]; + } + } + + /* return element i,j of infinite matrix A */ + private double eval_A(int i, int j) + { + return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1); + } + + /* multiply vector v by matrix A, each thread evaluate its range only */ + private void MultiplyAv(double[] v, double[] Av) + { + for (int i = range_begin; i < range_end; i++) + { + double sum = 0; + for (int j = 0; j < v.Length; j++) + sum += eval_A(i, j) * v[j]; + + Av[i] = sum; + } + } + + /* multiply vector v by matrix A transposed */ + private void MultiplyAtv(double[] v, double[] Atv) + { + for (int i = range_begin; i < range_end; i++) + { + double sum = 0; + for (int j = 0; j < v.Length; j++) + sum += eval_A(j, i) * v[j]; + + Atv[i] = sum; + } + } + + /* multiply vector v by matrix A and then by matrix A transposed */ + private void MultiplyAtAv(double[] v, double[] tmp, double[] AtAv) + { + + MultiplyAv(v, tmp); + // all thread must syn at completion + barrier.SignalAndWait(); + MultiplyAtv(tmp, AtAv); + // all thread must syn at completion + barrier.SignalAndWait(); + } + + } +} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.csproj new file mode 100644 index 000000000000..3f22766ae7ab --- /dev/null +++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-3.csproj @@ -0,0 +1,38 @@ + + + + + Debug + AnyCPU + 2.0 + {0B6702EB-3EED-41EB-B034-B3769918A476} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\ + .NETStandard,Version=v1.4 + netstandard1.4 + + + + + + pdbonly + true + + + + False + + + + + + + + + + + + $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json + + \ No newline at end of file diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs deleted file mode 100644 index 5f2b1aed5f67..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.cs +++ /dev/null @@ -1,128 +0,0 @@ -// 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. -/* The Computer Language Benchmarks Game - http://benchmarksgame.alioth.debian.org/ - - contributed by Isaac Gouy - - modified for use with xunit-performance -*/ - -using Microsoft.Xunit.Performance; -using System; - -[assembly: OptimizeForBenchmarks] - -namespace BenchmarksGame -{ -public class SpectralNorm -{ -#if DEBUG - public const int Iterations = 1; -#else - public const int Iterations = 300; -#endif - - public static int Main(String[] args) - { - int n = 100; - if (args.Length > 0) n = Int32.Parse(args[0]); - double norm = new SpectralNorm().Approximate(n); - Console.WriteLine("Norm={0:f9}", norm); - double expected = 1.274219991; - bool result = Math.Abs(norm - expected) < 1e-4; - return (result ? 100 : -1); - } - - [Benchmark] - public static void Bench() - { - int n = 100; - foreach (var iteration in Benchmark.Iterations) - { - double a = 0; - - using (iteration.StartMeasurement()) - { - for (int i = 0; i < Iterations; i++) - { - SpectralNorm s = new SpectralNorm(); - a += s.Approximate(n); - } - } - - double norm = a / Iterations; - double expected = 1.274219991; - bool valid = Math.Abs(norm - expected) < 1e-4; - if (!valid) - { - throw new Exception("Benchmark failed to validate"); - } - } - } - - private double Approximate(int n) - { - // create unit vector - double[] u = new double[n]; - for (int i = 0; i < n; i++) u[i] = 1; - - // 20 steps of the power method - double[] v = new double[n]; - for (int i = 0; i < n; i++) v[i] = 0; - - for (int i = 0; i < 10; i++) - { - MultiplyAtAv(n, u, v); - MultiplyAtAv(n, v, u); - } - - // B=AtA A multiplied by A transposed - // v.Bv /(v.v) eigenvalue of v - double vBv = 0, vv = 0; - for (int i = 0; i < n; i++) - { - vBv += u[i] * v[i]; - vv += v[i] * v[i]; - } - - return Math.Sqrt(vBv / vv); - } - - - /* return element i,j of infinite matrix A */ - private double A(int i, int j) - { - return 1.0 / ((i + j) * (i + j + 1) / 2 + i + 1); - } - - /* multiply vector v by matrix A */ - private void MultiplyAv(int n, double[] v, double[] Av) - { - for (int i = 0; i < n; i++) - { - Av[i] = 0; - for (int j = 0; j < n; j++) Av[i] += A(i, j) * v[j]; - } - } - - /* multiply vector v by matrix A transposed */ - private void MultiplyAtv(int n, double[] v, double[] Atv) - { - for (int i = 0; i < n; i++) - { - Atv[i] = 0; - for (int j = 0; j < n; j++) Atv[i] += A(j, i) * v[j]; - } - } - - /* multiply vector v by matrix A and then by matrix A transposed */ - private void MultiplyAtAv(int n, double[] v, double[] AtAv) - { - double[] u = new double[n]; - MultiplyAv(n, v, u); - MultiplyAtv(n, u, AtAv); - } -} -} diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj deleted file mode 100644 index 3cbd6d32db6a..000000000000 --- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm.csproj +++ /dev/null @@ -1,38 +0,0 @@ - - - - - Debug - AnyCPU - 2.0 - {95DFC527-4DC1-495E-97D7-E94EE1F7140D} - Exe - {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - ..\..\ - .NETStandard,Version=v1.4 - netstandard1.4 - - - - - - pdbonly - true - - - - False - - - - - - - - - - - - $(JitPackagesConfigFileDirectory)benchmark\obj\project.assets.json - - \ No newline at end of file