summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoseph Tremoulet <jotrem@microsoft.com>2017-08-31 14:32:57 -0400
committerJoseph Tremoulet <jotrem@microsoft.com>2017-09-15 13:28:10 -0400
commit4d9e8b539f5e9518d707f55624d43309bae266a2 (patch)
tree2328c2a6fd3d03d45aa7042ad4a6187b391256f9
parent19fc1cdcf46f971aff72387af06019a8740b30ed (diff)
downloadcoreclr-4d9e8b539f5e9518d707f55624d43309bae266a2.tar.gz
coreclr-4d9e8b539f5e9518d707f55624d43309bae266a2.tar.bz2
coreclr-4d9e8b539f5e9518d707f55624d43309bae266a2.zip
Update BenchmarksGame benchmarks to latest
For each benchmark, grab the current best C# .NET entry, and also grab the current best serial implementation (since these are easier to work with from the benchmarking perspective).
-rw-r--r--.gitattributes4
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-best.cs105
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-serial.cs86
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-best.cs127
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-serial.cs66
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-best.cs288
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-serial.cs176
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux-best.cs1
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-best.cs282
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-serial.cs165
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-best.cs72
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-serial.cs66
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-best.cs124
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-serial.cs2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body.csproj (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/nbody.csharp-3.cs (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-best.cs172
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-serial.cs2
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-best.cs74
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-serial.cs85
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-best.cs1
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25.txt (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25.txt)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25000.txt (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25000.txt)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp.csharp-1.cs (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-best.cs217
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-serial.cs108
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement.csproj (renamed from tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csproj)0
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-best.cs153
-rw-r--r--tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-serial.cs79
29 files changed, 2453 insertions, 2 deletions
diff --git a/.gitattributes b/.gitattributes
index 519ecbb037..add84340ad 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -69,8 +69,8 @@ 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/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/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-best.cs
new file mode 100644
index 0000000000..f559a51081
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-best.cs
@@ -0,0 +1,105 @@
+// 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
+// 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;
+
+public sealed class BinaryTrees
+{
+ public const int MinDepth = 4;
+
+ public static void Main(string[] args)
+ {
+ var n = args.Length == 0 ? 0 : int.Parse(args[0]);
+ 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<string>[(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<int>[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);
+
+ Console.WriteLine("stretch tree of depth {0}\t check: {1}",
+ stretchDepth, stretchDepthTask.Result);
+ foreach (var task in tasks)
+ Console.WriteLine(task.Result);
+ Console.WriteLine("long lived tree of depth {0}\t check: {1}",
+ maxDepth, maxDepthTask.Result);
+ }
+}
+
+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/binarytrees-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-serial.cs
new file mode 100644
index 0000000000..95732c6f33
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/binarytrees/binarytrees-serial.cs
@@ -0,0 +1,86 @@
+// 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
+// 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;
+
+class BinaryTrees
+{
+ const int minDepth = 4;
+
+ public static void Main(String[] args)
+ {
+ int n = 0;
+ if (args.Length > 0) n = Int32.Parse(args[0]);
+
+ int maxDepth = Math.Max(minDepth + 2, n);
+ int stretchDepth = maxDepth + 1;
+
+ int check = (TreeNode.bottomUpTree(stretchDepth)).itemCheck();
+ 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();
+ }
+
+ Console.WriteLine("{0}\t trees of depth {1}\t check: {2}",
+ iterations, depth, check);
+ }
+
+ Console.WriteLine("long lived tree of depth {0}\t check: {1}",
+ maxDepth, longLivedTree.itemCheck());
+ }
+
+
+ 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/fannkuch-redux/fannkuch-redux-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-best.cs
new file mode 100644
index 0000000000..470b67beaf
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-best.cs
@@ -0,0 +1,127 @@
+// 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
+// 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;
+
+public static class FannkuchRedux
+{
+ 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 void Main(string[] args)
+ {
+ int n = args.Length > 0 ? int.Parse(args[0]) : 7;
+ 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];
+ }
+ Console.Out.WriteLineAsync(chksum + "\nPfannkuchen(" + n + ") = " + maxflips);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-serial.cs
new file mode 100644
index 0000000000..646b68d2b4
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fannkuch-redux/fannkuch-redux-serial.cs
@@ -0,0 +1,66 @@
+// 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
+// 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;
+
+class FannkuchRedux
+{
+ 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 void 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]);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-best.cs
new file mode 100644
index 0000000000..3430c37a6b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-best.cs
@@ -0,0 +1,288 @@
+// 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
+// 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;
+
+class Fasta
+{
+ const int LineLength = 60;
+
+ const int IM = 139968;
+ const int IA = 3877;
+ const int IC = 29573;
+ static int seed = 42;
+
+ public static void Main(string[] args)
+ {
+ int n = args.Length > 0 ? Int32.Parse(args[0]) : 1000;
+
+ MakeCumulative(IUB);
+ MakeCumulative(HomoSapiens);
+
+ using (var s = Console.OpenStandardOutput())
+ {
+ 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<R> TransformQueue<T, R>(BlockingCollection<T> queue,
+ Func<T, R> transform, int threadCount)
+ {
+ var tasks = new Task<R>[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<int[]>(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/fasta/fasta-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-serial.cs
new file mode 100644
index 0000000000..e91c6f8dff
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fasta/fasta-serial.cs
@@ -0,0 +1,176 @@
+// 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
+// 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 <alp@atoker.com>
+*/
+
+using System;
+using System.IO;
+using System.Text;
+
+class Fasta
+{
+ static void Main (string[] args) {
+ MakeCumulative (HomoSapiens);
+ MakeCumulative (IUB);
+
+ int n = args.Length > 0 ? Int32.Parse (args[0]) : 1000;
+
+ using (Stream s = Console.OpenStandardOutput ()) {
+ 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/fastaredux/fastaredux-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux-best.cs
new file mode 100644
index 0000000000..691fde3aac
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/fastaredux/fastaredux-best.cs
@@ -0,0 +1 @@
+// no longer up on site \ No newline at end of file
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-best.cs
new file mode 100644
index 0000000000..2b648ddd56
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-best.cs
@@ -0,0 +1,282 @@
+// 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
+// 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;
+
+class Wrapper { public int v=1; }
+public static class KNucleotide
+{
+ const int BLOCK_SIZE = 1024 * 1024 * 8;
+ static List<byte[]> threeBlocks = new List<byte[]>();
+ 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()
+ {
+ var stream = Console.OpenStandardInput();
+
+ // 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<byte>());
+ 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<long, Wrapper> 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<long, Wrapper> 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<string> count(int l, long mask, Func<Dictionary<long,Wrapper>,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<long,Wrapper>();
+ 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<long,Wrapper> 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<long,Wrapper>();
+ 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<string> count4(int l, long mask, Func<Dictionary<long,Wrapper>,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<long,Wrapper>(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<long,Wrapper> freq, int fragmentLength)
+ {
+ var sb = new StringBuilder();
+ double percent = 100.0 / freq.Values.Sum(i => i.v);
+ foreach(var kv in freq.OrderByDescending(i => i.Value.v))
+ {
+ 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<long,Wrapper> dictionary, string fragment)
+ {
+ 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;
+ return string.Concat(n.ToString(), "\t", fragment);
+ }
+
+ public static void Main(string[] args)
+ {
+ 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;
+
+ loadThreeData();
+
+ Parallel.ForEach(threeBlocks, bytes =>
+ {
+ for(int i=0; i<bytes.Length; i++)
+ bytes[i] = tonum[bytes[i]];
+ });
+
+ var task18 = count4(18, 34359738367, d => writeCount(d, "GGTATTTTAATTTATAGT"));
+ var task12 = count4(12, 8388607, d => writeCount(d, "GGTATTTTAATT"));
+ var task6 = count(6, 0b1111111111, d => writeCount(d, "GGTATT"));
+ var task4 = count(4, 0b111111, d => writeCount(d, "GGTA"));
+ var task3 = count(3, 0b1111, d => writeCount(d, "GGT"));
+ var task2 = count(2, 0b11, d => writeFrequencies(d, 2));
+ var task1 = count(1, 0, d => writeFrequencies(d, 1));
+
+ 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);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-serial.cs
new file mode 100644
index 0000000000..b5add5fe00
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/k-nucleotide/k-nucleotide-serial.cs
@@ -0,0 +1,165 @@
+// 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
+// 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;
+
+public struct ByteString : IEquatable<ByteString>
+{
+ 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<string> 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 program {
+
+
+ public static void Main(string[] args) {
+ string line;
+ StreamReader source = new StreamReader(Console.OpenStandardInput());
+ var input = new List<string>();
+
+ 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;
+ for (int f = 1; f < 3; f++) kn.WriteFrequencies(f);
+ foreach (var seq in
+ new[] { "GGT", "GGTA", "GGTATT", "GGTATTTTAATT",
+ "GGTATTTTAATTTATAGT"})
+ kn.WriteCount(seq);
+
+ }
+}
+
+public class KNucleotide {
+
+ private class Count {
+ public int V;
+ public Count(int v) { V = v; }
+ }
+
+ private Dictionary<ByteString, Count> frequencies
+ = new Dictionary<ByteString, Count>();
+ private byte[] sequence;
+
+ public KNucleotide(byte[] s) { sequence = s; }
+
+ public void WriteFrequencies(int length) {
+ GenerateFrequencies(length);
+ var items = new List<KeyValuePair<ByteString, Count>>(frequencies);
+ items.Sort(SortByFrequencyAndCode);
+ double percent = 100.0 / (sequence.Length - length + 1);
+ foreach (var item in items)
+ Console.WriteLine("{0} {1:f3}",
+ item.Key.ToString(), item.Value.V * percent);
+ Console.WriteLine();
+ }
+
+ public void WriteCount(string fragment) {
+ GenerateFrequencies(fragment.Length);
+ Count count;
+ if (!frequencies.TryGetValue(new ByteString(fragment), out count))
+ count = new Count(0);
+ Console.WriteLine("{0}\t{1}", count.V, fragment);
+ }
+
+ 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<ByteString, Count> i0,
+ KeyValuePair<ByteString, Count> 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/mandelbrot/mandelbrot-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-best.cs
new file mode 100644
index 0000000000..9e6912a691
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-best.cs
@@ -0,0 +1,72 @@
+// 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
+// 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;
+
+public class MandelBrot
+{
+ [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 void Main (String[] args)
+ {
+ var n = args.Length > 0 ? Int32.Parse(args[0]) : 200;
+ 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);
+ });
+ Console.Out.WriteLine("P4\n{0} {0}", n);
+ Console.OpenStandardOutput().Write(data, 0, data.Length);
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-serial.cs
new file mode 100644
index 0000000000..66748b3751
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/mandelbrot/mandelbrot-serial.cs
@@ -0,0 +1,66 @@
+// 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
+// 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;
+
+class Mandelbrot {
+
+ public static void Main(String[] args) {
+
+ int width = 100;
+ if (args.Length > 0)
+ width = Int32.Parse(args[0]);
+
+ int height = width;
+ int maxiter = 50;
+ double limit = 4.0;
+
+ Console.WriteLine("P4");
+ Console.WriteLine("{0} {1}", width,height);
+ Stream s = Console.OpenStandardOutput(1024);
+
+ 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));
+ }
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-best.cs
new file mode 100644
index 0000000000..2d5ec96ee6
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-best.cs
@@ -0,0 +1,124 @@
+// 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
+// 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;
+
+class NBody {
+ public static void Main(String[] args) {
+ int n = args.Length > 0 ? Int32.Parse(args[0]) : 10000;
+ NBodySystem bodies = new NBodySystem();
+ Console.WriteLine("{0:f9}", bodies.Energy());
+ for (int i = 0; i < n; i++) bodies.Advance(0.01);
+ Console.WriteLine("{0:f9}", bodies.Energy());
+ }
+}
+
+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/n-body/n-body-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-serial.cs
new file mode 100644
index 0000000000..6d7970df3f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body-serial.cs
@@ -0,0 +1,2 @@
+// best is serial
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body.csproj
index 5df299a93e..5df299a93e 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csproj
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/n-body.csproj
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/nbody.csharp-3.cs
index 60e083ad11..60e083ad11 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/nbody/nbody.csharp-3.cs
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/n-body/nbody.csharp-3.cs
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-best.cs
new file mode 100644
index 0000000000..f9078e51be
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-best.cs
@@ -0,0 +1,172 @@
+// 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
+// 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/
+ *
+ * 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.Text;
+using System.Runtime.InteropServices;
+
+public class pidigits {
+
+ GmpInteger q = new GmpInteger(), r = new GmpInteger(), s = new GmpInteger(), t = new GmpInteger();
+ GmpInteger u = new GmpInteger(), v = new GmpInteger(), w = new GmpInteger();
+
+ int i;
+ StringBuilder strBuf = new StringBuilder (40);
+ int n;
+
+ pidigits (int n)
+ {
+ this.n=n;
+ }
+
+ private void compose_r(int bq, int br, int bs, int bt)
+ {
+ u.mul(r, bs);
+ r.mul(r, bq);
+ v.mul(t, br);
+ r.add(r, v);
+ t.mul(t, bt);
+ t.add(t, u);
+ s.mul(s, bt);
+ u.mul(q, bs);
+ s.add(s, u);
+ q.mul(q, bq);
+ }
+
+ /* Compose matrix with numbers on the left. */
+ private void compose_l(int bq, int br, int bs, int bt)
+ {
+ r.mul(r, bt);
+ u.mul(q, br);
+ r.add(r, u);
+ u.mul(t, bs);
+ t.mul(t, bt);
+ v.mul(s, br);
+ t.add(t, v);
+ s.mul(s, bq);
+ s.add(s, u);
+ q.mul(q, bq);
+ }
+
+ /* Extract one digit. */
+ private int extract(int j)
+ {
+ u.mul(q, j);
+ u.add(u, r);
+ v.mul(s, j);
+ v.add(v, t);
+ w.div(u, v);
+ return w.intValue();
+ }
+
+ /* Print one digit. Returns 1 for the last digit. */
+ private bool prdigit(int y)
+ {
+ 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);
+ Console.WriteLine(strBuf);
+ strBuf = new StringBuilder(40);
+ }
+ return i == n;
+ }
+
+ /* Generate successive digits of PI. */
+ void Run()
+ {
+ int k = 1;
+ i = 0;
+ q.set(1);
+ r.set(0);
+ s.set(0);
+ t.set(1);
+ for (;;) {
+ int y = extract(3);
+ if (y == extract(4)) {
+ if (prdigit(y)) return;
+ compose_r(10, -10*y, 0, 1);
+ } else {
+ compose_l(k, 4*k+2, 0, 2*k+1);
+ k++;
+ }
+ }
+ }
+
+ public static void Main(String[] args) {
+ pidigits m = new pidigits(Int32.Parse (args[0]));
+ m.Run();
+ }
+}
+
+[StructLayout (LayoutKind.Sequential)]
+struct mpz_t {
+ public int _mp_alloc;
+ public int _mp_size;
+ public IntPtr ptr;
+}
+
+class GmpInteger {
+
+ // Public methods
+
+ public GmpInteger() {
+ mpz_init(ref pointer);
+ }
+
+ public GmpInteger(int value) {
+ mpz_set_si(ref pointer, value);
+ }
+
+ public void set(int value) { mpz_set_si(ref pointer, value); }
+
+ public void mul(GmpInteger src, int val) { mpz_mul_si(ref pointer, ref src.pointer, val); }
+
+ public void add(GmpInteger op1, GmpInteger op2) { mpz_add(ref pointer, ref op1.pointer, ref op2.pointer); }
+
+ public void div(GmpInteger op1, GmpInteger op2) { mpz_tdiv_q(ref pointer, ref op1.pointer, ref op2.pointer); }
+
+ public int intValue() { return mpz_get_si(ref pointer); }
+
+ public double doubleValue() { return mpz_get_d(ref pointer); }
+
+ // Non public stuff
+
+ mpz_t pointer;
+
+ [DllImport ("gmp", EntryPoint="__gmpz_init")]
+ extern static void mpz_init(ref mpz_t value);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_mul_si")]
+ extern static void mpz_mul_si(ref mpz_t dest, ref mpz_t src, int val);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_add")]
+ extern static void mpz_add(ref mpz_t dest, ref mpz_t src, ref mpz_t src2);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_tdiv_q")]
+ extern static void mpz_tdiv_q(ref mpz_t dest, ref mpz_t src, ref mpz_t src2);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_set_si")]
+ extern static void mpz_set_si(ref mpz_t src, int value);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_get_si")]
+ extern static int mpz_get_si(ref mpz_t src);
+
+ [DllImport ("gmp", EntryPoint="__gmpz_get_d")]
+ extern static double mpz_get_d(ref mpz_t src);
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-serial.cs
new file mode 100644
index 0000000000..6d7970df3f
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/pidigits/pidigits-serial.cs
@@ -0,0 +1,2 @@
+// best is serial
+
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-best.cs
new file mode 100644
index 0000000000..b945bc31b2
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-best.cs
@@ -0,0 +1,74 @@
+// 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
+// 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.Threading.Tasks;
+using System.Text.RegularExpressions;
+
+public static class regexredux
+{
+ 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 void Main(string[] args)
+ {
+ var sequences = Console.In.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"));
+
+ 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());
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-serial.cs
new file mode 100644
index 0000000000..12a44b8e29
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regex-redux/regex-redux-serial.cs
@@ -0,0 +1,85 @@
+// 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
+// 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.Text.RegularExpressions;
+
+class regexredux
+{
+ static void Main(string[] args){
+
+ // read FASTA sequence
+ String sequence = Console.In.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++;
+ 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);
+ }
+ Console.WriteLine("\n{0}\n{1}\n{2}",
+ initialLength, codeLength, 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-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-best.cs
new file mode 100644
index 0000000000..d261a0d286
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/regexdna/regexdna-best.cs
@@ -0,0 +1 @@
+// no longer up on site
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
index f749b06ea7..f749b06ea7 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25.txt
+++ b/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
index fd4414b176..fd4414b176 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp-input25000.txt
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp-input25000.txt
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp.csharp-1.cs
index bca63bd00e..bca63bd00e 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csharp-1.cs
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/revcomp.csharp-1.cs
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-best.cs
new file mode 100644
index 0000000000..8cd35688ac
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-best.cs
@@ -0,0 +1,217 @@
+// 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
+// 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.Threading;
+
+class RevCompSequence { public List<byte[]> Pages; public int StartHeader, EndExclusive; public Thread ReverseThread; }
+
+public static class revcomp
+{
+ const int READER_BUFFER_SIZE = 1024 * 1024;
+ const byte LF = 10, GT = (byte)'>', SP = 32;
+ static BlockingCollection<byte[]> readQue = new BlockingCollection<byte[]>();
+ static BlockingCollection<RevCompSequence> writeQue = new BlockingCollection<RevCompSequence>();
+ 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 void Reader()
+ {
+ using (var stream = Console.OpenStandardInput())
+ {
+ 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<T>(BlockingCollection<T> q, out T t) where T : class
+ {
+ t = null;
+ while(!q.IsCompleted && !q.TryTake(out t)) Thread.SpinWait(0);
+ 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[]>();
+ byte[] bytes;
+ while (tryTake(readQue, out bytes))
+ {
+ data.Add(bytes);
+ while((i=Array.IndexOf<byte>(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<byte[]> { bytes };
+ }
+ }
+ i = Array.IndexOf<byte>(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<byte>(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 void Writer()
+ {
+ using (var stream = Console.OpenStandardOutput())
+ {
+ 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);
+ }
+ }
+ }
+
+ public static void Main(string[] args)
+ {
+ new Thread(Reader).Start();
+ new Thread(Grouper).Start();
+ Writer();
+ }
+}
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-serial.cs
new file mode 100644
index 0000000000..5838e2f92b
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement-serial.cs
@@ -0,0 +1,108 @@
+// 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
+// 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;
+
+static class revcomp
+{
+ 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 void Main(string[] args) {
+ InitComplements();
+ var seq = new List<byte[]>();
+ var b = new Block { Count = -1 };
+ Index line = Index.None, start = Index.None, end = Index.None;
+ using (var r = new BinaryReader(Console.OpenStandardInput())) {
+ using (var w = Console.OpenStandardOutput()) {
+ 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<byte[]> 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.csproj
index 00789ed3a5..00789ed3a5 100644
--- a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/revcomp/revcomp.csproj
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/reverse-complement/reverse-complement.csproj
diff --git a/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-best.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-best.cs
new file mode 100644
index 0000000000..c82f002147
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-best.cs
@@ -0,0 +1,153 @@
+// 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
+// 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.Threading;
+using System.Threading.Tasks;
+
+namespace SpectralNorms
+{
+ class SpectralNorm
+ {
+ public static void Main(String[] args)
+ {
+ int n = 100;
+ if (args.Length > 0) n = Int32.Parse(args[0]);
+
+ Console.WriteLine("{0:f9}", spectralnormGame(n));
+ }
+
+ private static double spectralnormGame(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-serial.cs b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-serial.cs
new file mode 100644
index 0000000000..4ea25857ee
--- /dev/null
+++ b/tests/src/JIT/Performance/CodeQuality/BenchmarksGame/spectralnorm/spectralnorm-serial.cs
@@ -0,0 +1,79 @@
+// 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
+// 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;
+
+class SpectralNorm
+{
+ public static void Main(String[] args) {
+ int n = 100;
+ if (args.Length > 0) n = Int32.Parse(args[0]);
+
+ Console.WriteLine("{0:f9}", new SpectralNorm().Approximate(n));
+ }
+
+ 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 */
+ 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);
+ }
+}