Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 304b884

Browse files
committed
Merge pull request #2749 from axelheer/biginteger-benchmark
Add performance tests for BigInteger
2 parents 0038741 + 88531c6 commit 304b884

File tree

2 files changed

+199
-0
lines changed

2 files changed

+199
-0
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
using System;
2+
using System.Diagnostics;
3+
using Xunit;
4+
using Xunit.Abstractions;
5+
6+
namespace System.Numerics.Tests
7+
{
8+
public class PerformanceTests
9+
{
10+
private readonly Random _random;
11+
private readonly ITestOutputHelper _output;
12+
13+
public PerformanceTests(ITestOutputHelper output)
14+
{
15+
_random = new Random(1138);
16+
_output = output;
17+
}
18+
19+
[Theory]
20+
[ActiveIssue("PerformanceTest")]
21+
[InlineData(1000000, 16, 16)]
22+
[InlineData(1000000, 64, 64)]
23+
[InlineData(1000000, 256, 256)]
24+
[InlineData(1000000, 1024, 1024)]
25+
[InlineData(100000, 4096, 4096)]
26+
[InlineData(100000, 16384, 16384)]
27+
[InlineData(100000, 65536, 65536)]
28+
public void Add(int count, int leftBits, int rightBits)
29+
{
30+
RunBenchmark(count, leftBits, rightBits, (l, r) => BigInteger.Add(l, r));
31+
}
32+
33+
[Theory]
34+
[ActiveIssue("PerformanceTest")]
35+
[InlineData(1000000, 16, 16)]
36+
[InlineData(1000000, 64, 64)]
37+
[InlineData(1000000, 256, 256)]
38+
[InlineData(1000000, 1024, 1024)]
39+
[InlineData(100000, 4096, 4096)]
40+
[InlineData(100000, 16384, 16384)]
41+
[InlineData(100000, 65536, 65536)]
42+
public void Subtract(int count, int leftBits, int rightBits)
43+
{
44+
RunBenchmark(count, leftBits, rightBits, (l, r) => BigInteger.Subtract(l, r));
45+
}
46+
47+
[Theory]
48+
[ActiveIssue("PerformanceTest")]
49+
[InlineData(1000000, 16, 16)]
50+
[InlineData(1000000, 64, 64)]
51+
[InlineData(1000000, 256, 256)]
52+
[InlineData(100000, 1024, 1024)]
53+
[InlineData(10000, 4096, 4096)]
54+
[InlineData(1000, 16384, 16384)]
55+
[InlineData(100, 65536, 65536)]
56+
public void Multiply(int count, int leftBits, int rightBits)
57+
{
58+
RunBenchmark(count, leftBits, rightBits, (l, r) => BigInteger.Multiply(l, r));
59+
}
60+
61+
[Theory]
62+
[ActiveIssue("PerformanceTest")]
63+
[InlineData(1000000, 16)]
64+
[InlineData(1000000, 64)]
65+
[InlineData(1000000, 256)]
66+
[InlineData(100000, 1024)]
67+
[InlineData(10000, 4096)]
68+
[InlineData(1000, 16384)]
69+
[InlineData(100, 65536)]
70+
public void Square(int count, int bits)
71+
{
72+
RunBenchmark(count, bits, v => BigInteger.Multiply(v, v));
73+
}
74+
75+
[Theory]
76+
[ActiveIssue("PerformanceTest")]
77+
[InlineData(1000000, 16, 16)]
78+
[InlineData(1000000, 64, 16)]
79+
[InlineData(1000000, 256, 128)]
80+
[InlineData(100000, 1024, 512)]
81+
[InlineData(10000, 4096, 2048)]
82+
[InlineData(1000, 16384, 8192)]
83+
[InlineData(100, 65536, 32768)]
84+
public void Divide(int count, int leftBits, int rightBits)
85+
{
86+
RunBenchmark(count, leftBits, rightBits, (l, r) => BigInteger.Divide(l, r));
87+
}
88+
89+
[Theory]
90+
[ActiveIssue("PerformanceTest")]
91+
[InlineData(1000000, 16, 16)]
92+
[InlineData(1000000, 64, 16)]
93+
[InlineData(1000000, 256, 128)]
94+
[InlineData(100000, 1024, 512)]
95+
[InlineData(10000, 4096, 2048)]
96+
[InlineData(1000, 16384, 8192)]
97+
[InlineData(100, 65536, 32768)]
98+
public void Remainder(int count, int leftBits, int rightBits)
99+
{
100+
RunBenchmark(count, leftBits, rightBits, (l, r) => BigInteger.Remainder(l, r));
101+
}
102+
103+
[Theory]
104+
[ActiveIssue("PerformanceTest")]
105+
[InlineData(100000, 16, 16, 16)]
106+
[InlineData(10000, 64, 64, 64)]
107+
[InlineData(1000, 256, 256, 256)]
108+
[InlineData(100, 1024, 1024, 1024)]
109+
[InlineData(10, 4096, 4096, 4096)]
110+
[InlineData(1, 16384, 16384, 16384)]
111+
public void ModPow(int count, int leftBits, int rightBits, int otherBits)
112+
{
113+
RunBenchmark(count, leftBits, rightBits, otherBits, (l, r, o) => BigInteger.ModPow(l, r, o));
114+
}
115+
116+
private void RunBenchmark(int count, int bits, Action<BigInteger> operation)
117+
{
118+
BigInteger[] value = CreateIntegerSeed(count, bits);
119+
120+
long result = RunBenchmark(count, i => operation(value[i]));
121+
122+
_output.WriteLine("({1:N0}) : {2:N0} ms / {0:N0} ops", count, bits, result);
123+
}
124+
125+
private void RunBenchmark(int count, int leftBits, int rightBits, Action<BigInteger, BigInteger> operation)
126+
{
127+
BigInteger[] left = CreateIntegerSeed(count, leftBits);
128+
BigInteger[] right = CreateIntegerSeed(count, rightBits);
129+
130+
long result = RunBenchmark(count, i => operation(left[i], right[i]));
131+
132+
_output.WriteLine("({1:N0}, {2:N0}) : {3:N0} ms / {0:N0} ops", count, leftBits, rightBits, result);
133+
}
134+
135+
private void RunBenchmark(int count, int leftBits, int rightBits, int otherBits, Action<BigInteger, BigInteger, BigInteger> operation)
136+
{
137+
BigInteger[] left = CreateIntegerSeed(count, leftBits);
138+
BigInteger[] right = CreateIntegerSeed(count, rightBits);
139+
BigInteger[] other = CreateIntegerSeed(count, otherBits);
140+
141+
long result = RunBenchmark(count, i => operation(left[i], right[i], other[i]));
142+
143+
_output.WriteLine("({1:N0}, {2:N0}, {3:N0}) : {4:N0} ms / {0:N0} ops", count, leftBits, rightBits, otherBits, result);
144+
}
145+
146+
private const int MAX_SEED = 10;
147+
private const int RUN_COUNT = 3;
148+
149+
private long RunBenchmark(int count, Action<int> operation)
150+
{
151+
Stopwatch watch = new Stopwatch();
152+
long result = long.MaxValue;
153+
154+
operation(0);
155+
156+
for (int j = 0; j < RUN_COUNT; j++)
157+
{
158+
watch.Restart();
159+
for (int i = 0; i < count; i++)
160+
operation(i % MAX_SEED);
161+
watch.Stop();
162+
163+
result = Math.Min(result, watch.ElapsedMilliseconds);
164+
}
165+
166+
return result;
167+
}
168+
169+
private BigInteger[] CreateIntegerSeed(int count, int bits)
170+
{
171+
BigInteger[] seed = new BigInteger[Math.Min(count, MAX_SEED)];
172+
173+
for (int i = 0; i < seed.Length; i++)
174+
seed[i] = CreateRandomInteger(bits);
175+
176+
return seed;
177+
}
178+
179+
private BigInteger CreateRandomInteger(int bits)
180+
{
181+
byte[] value = new byte[(bits + 8) / 8];
182+
BigInteger result = BigInteger.Zero;
183+
184+
while (result.IsZero)
185+
{
186+
_random.NextBytes(value);
187+
188+
// ensure actual bit count (remaining bits not set)
189+
// ensure positive value (highest-order bit not set)
190+
value[value.Length - 1] &= (byte)(0xFF >> 8 - bits % 8);
191+
192+
result = new BigInteger(value);
193+
}
194+
195+
return result;
196+
}
197+
}
198+
}

src/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
<Compile Include="BigInteger\op_subtract.cs" />
6969
<Compile Include="BigInteger\op_xor.cs" />
7070
<Compile Include="BigInteger\parse.cs" />
71+
<Compile Include="BigInteger\PerformanceTests.cs" />
7172
<Compile Include="BigInteger\pow.cs" />
7273
<Compile Include="BigInteger\properties.cs" />
7374
<Compile Include="BigInteger\remainder.cs" />

0 commit comments

Comments
 (0)