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