-
-
Save VisualMelon/0c169ba3a3c23c53c0a4a28ff3af7bd4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using BenchmarkDotNet.Attributes; | |
using System.Runtime; | |
using System.Runtime.CompilerServices; | |
using System.Linq; | |
using System.Collections.Generic; | |
namespace SpanVsArray | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
BenchmarkDotNet.Running.BenchmarkRunner.Run<Bench>(); | |
} | |
} | |
public class Bench | |
{ | |
[BenchmarkDotNet.Attributes.Params(5, 10, 30)] | |
public int N { get; set; } | |
[Benchmark] | |
public void OP() | |
{ | |
PascalTriangle.Generate(N); | |
} | |
[Benchmark] | |
public void Jodrell() | |
{ | |
JodrellPascal.Triangle(N); | |
} | |
[Benchmark] | |
public void JodrellNoSpan() | |
{ | |
JodrellPascalNoSpan.Triangle(N); | |
} | |
[Benchmark] | |
public void JodrellNoSpanCache() | |
{ | |
JodrellPascalNoSpanCache.Triangle(N); | |
} | |
[Benchmark] | |
public void PeterPerRow() | |
{ | |
Peter.Generate_PerRow_Reflective(N); | |
} | |
[Benchmark] | |
public void PeterMelon() | |
{ | |
Peter.Generate_Array_Improved_Reflective(N); | |
} | |
} | |
public static class JodrellPascal | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ReadOnlySpan<int[]> Triangle(int n) | |
{ | |
if (n < 1) | |
{ | |
return ReadOnlySpan<int[]>.Empty; | |
} | |
Span<int[]> triangle = new int[n][]; | |
for (var r = 0; r < n; r++) | |
{ | |
triangle[r] = Line(r).ToArray(); | |
} | |
return triangle; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ReadOnlySpan<int> Line(int n) | |
{ | |
if (n < 0) | |
{ | |
return ReadOnlySpan<int>.Empty; | |
} | |
if (n == 0) | |
{ | |
return (ReadOnlySpan<int>)new int[] | |
{ | |
1 | |
}; | |
} | |
Span<int> result = new int[n + 1]; | |
result[0] = 1; | |
for (var k = 0; k < n; k++) | |
{ | |
result[k + 1] = result[k] * (n - k) / (k + 1); | |
} | |
return result; | |
} | |
} | |
public static class JodrellPascalNoSpan | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ReadOnlySpan<int[]> Triangle(int n) | |
{ | |
if (n < 1) | |
{ | |
return ReadOnlySpan<int[]>.Empty; | |
} | |
Span<int[]> triangle = new int[n][]; | |
for (var r = 0; r < n; r++) | |
{ | |
triangle[r] = Line(r); | |
} | |
return triangle; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static int[] Line(int n) | |
{ | |
if (n < 0) | |
{ | |
return Array.Empty<int>(); | |
} | |
if (n == 0) | |
{ | |
return new int[] | |
{ | |
1 | |
}; | |
} | |
int[] result = new int[n + 1]; | |
result[0] = 1; | |
for (var k = 0; k < n; k++) | |
{ | |
result[k + 1] = result[k] * (n - k) / (k + 1); | |
} | |
return result; | |
} | |
} | |
public static class JodrellPascalNoSpanCache | |
{ | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static ReadOnlySpan<int[]> Triangle(int n) | |
{ | |
if (n < 1) | |
{ | |
return ReadOnlySpan<int[]>.Empty; | |
} | |
Span<int[]> triangle = new int[n][]; | |
for (var r = 0; r < n; r++) | |
{ | |
triangle[r] = Line(r); | |
} | |
return triangle; | |
} | |
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |
public static int[] Line(int n) | |
{ | |
if (n < 0) | |
{ | |
return Array.Empty<int>(); | |
} | |
if (n == 0) | |
{ | |
return new int[] | |
{ | |
1 | |
}; | |
} | |
int[] result = new int[n + 1]; | |
var last = result[0] = 1; | |
for (var k = 0; k < n; k++) | |
{ | |
last = result[k + 1] = last * (n - k) / (k + 1); | |
} | |
return result; | |
} | |
} | |
public class PascalTriangle | |
{ | |
public static IList<IList<int>> Generate(int numRows) | |
{ | |
IList<IList<int>> result = new List<IList<int>>(); | |
if (numRows == 0) | |
{ | |
return result; | |
} | |
List<int> row = new List<int>(); | |
row.Add(1); | |
result.Add(row); | |
if (numRows == 1) | |
{ | |
return result; | |
} | |
for (int i = 1; i < numRows; i++) | |
{ | |
var prevRow = result[i - 1]; | |
row = new List<int>(); | |
row.Add(1); | |
for (int j = 0; j < prevRow.Count - 1; j++) | |
{ | |
row.Add(prevRow[j] + prevRow[j + 1]); | |
} | |
row.Add(1); | |
result.Add(row); | |
} | |
return result; | |
} | |
} | |
public class Peter | |
{ | |
// Using arrays, calculating each row individually, using row reflection: | |
public static IList<IList<int>> Generate_PerRow_Reflective(int numRows) | |
{ | |
var result = new int[numRows][]; | |
for (int i = 0; i < numRows; i++) | |
{ | |
var row = new int[i + 1]; | |
row[0] = 1; | |
row[i] = 1; | |
var mid = i / 2; | |
for (int j = 0; j < mid; j++) | |
{ | |
var value = row[j] * (i - j) / (j + 1); | |
row[j + 1] = value; | |
row[i - j - 1] = value; | |
} | |
result[i] = row; | |
} | |
return result; | |
} | |
// Using arrays instead of lists, caching the previous row's left value, and using row reflection: | |
public static IList<IList<int>> Generate_Array_Improved_Reflective(int numRows) | |
{ | |
var result = new int[numRows][]; | |
if (numRows == 0) | |
return result; | |
result[0] = new int[] { 1 }; | |
if (numRows == 1) | |
return result; | |
for (int i = 1; i < numRows; i++) | |
{ | |
var prevRow = result[i - 1]; | |
var row = new int[i + 1]; | |
var left = 0; | |
var mid = (i / 2) + 1; | |
for (int j = 0; j < mid; j++) | |
{ | |
int right = prevRow[j]; | |
var sum = left + right; | |
row[j] = sum; | |
row[i - j] = sum; | |
left = right; | |
} | |
result[i] = row; | |
} | |
return result; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Very nice data!