[C #] I tried to verify the speed of the loop statement Part 2
Last time, I summarized the speed verification of loop statements in C #. Since there were many places where the verification method was immature, we will carry out verification using BenchmarkDotNet
introduced by @Midoliy this time.
To carry out
- Prepare an array and list with 100 million elements.
- Verify the prepared array and list.
- Simply spin around.
- Add multiples of 2 while turning around.
Target loop statement
- for
- foreach
- do
- do-while
- LINQ (Query format): Only add-in verification is performed
- LINQ (Method format): Only add-in verification is performed
result
Simply spin around (array)
Method | Mean | Error | StdDev | Median | --------------------------- |----------:|-----------:|-----------:|----------:|
BenchFor_Array | 29.08 ms | 0.1590 ms | 0.1410 ms | 29.05 ms |
BenchForEach_Array | 48.22 ms | 0.0428 ms | 0.0334 ms | 48.22 ms |
BenchDo_Array | 28.93 ms | 0.0829 ms | 0.0735 ms | 28.93 ms |
BenchDoWhile_Array | 36.09 ms | 2.6406 ms | 7.7859 ms | 33.17 ms |
Simply spin around (list)
Method | Mean | Error | StdDev | Median | --------------------------- |----------:|-----------:|-----------:|----------:|
BenchFor_List | 36.53 ms | 0.4746 ms | 0.4439 ms | 36.40 ms |
BenchForEach_List | **248.81 ms** | 10.3583 ms | 12.3308 ms | 244.77 ms |
BenchDo_List | 36.49 ms | 0.4889 ms | 0.4573 ms | 36.30 ms |
BenchDoWhile_List | 36.19 ms | 0.1416 ms | 0.1182 ms | 36.19 ms | * The reason why the speed of foreach changes so much between arrays and lists was very easy to understand from @ Tokeiya's [for and foreach for arrays](https://qiita.com/Tokeiya/items/5f69f0b0233c62967820).
Addition of multiples of 2 (array)
Method | Mean | Error | StdDev | Median | --------------------------- |----------:|-----------:|-----------:|----------:|
BenchForWithCalc_Array | 151.77 ms | 0.3014 ms | 0.2819 ms | 151.79 ms | BenchForEachWithCalc_Array | **136.51 ms** | 0.1996 ms | 0.1867 ms | 136.46 ms |
BenchDoWithCalc_Array | 151.72 ms | 0.2464 ms | 0.2305 ms | 151.65 ms | BenchDoWhileWithCalc_Array | 151.03 ms | 1.1535 ms | 1.0225 ms | 150.97 ms |
BenchLINQQuery_Array | 611.51 ms | 5.0230 ms | 4.6985 ms | 613.74 ms |
BenchLINQMethod_Array | 589.09 ms | 11.6493 ms | 11.4412 ms | 586.88 ms | ### Addition of multiples of 2 (list)
Method | Mean | Error | StdDev | Median | --------------------------- |----------:|-----------:|-----------:|----------:|
BenchForWithCalc_List | 169.25 ms | 0.3809 ms | 0.3563 ms | 169.37 ms | BenchForEachWithCalc_List | **299.09 ms** | 3.3102 ms | 3.0963 ms | 300.62 ms |
BenchDoWithCalc_List | 172.82 ms | 2.8077 ms | 2.1921 ms | 173.18 ms | BenchDoWhileWithCalc_List | 169.38 ms | 0.5669 ms | 0.4734 ms | 169.22 ms |
BenchLINQQuery_List | 814.73 ms | 5.5605 ms | 5.2013 ms | 816.72 ms |
BenchLINQMethod_List | 825.85 ms | 7.5451 ms | 6.6885 ms | 825.91 ms |
Mean : Arithmetic mean of all measurements
Error : Half of 99.9% confidence interval
StdDev : Standard deviation of all measurements
Median : Value separating the higher half of all measurements (50th percentile)
Validation source
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
using System.Collections.Generic;
using System.Linq;
namespace Benchmarks
{
public class LoopBenchmarkTest
{
private static readonly int listCnt = 100_000_000; //Element count
private static readonly int[] numArray; //Validation array
private static readonly List<int> numList; //Validation list
static LoopBenchmarkTest()
{
numArray = Enumerable.Range(0, listCnt).ToArray();
numList = new List<int>(numArray);
}
#region Array
[Benchmark]
public long BenchFor_Array()
{
for (var i = 0; i <= numArray.Length - 1; i++) {}
return 0;
}
[Benchmark]
public long BenchForEach_Array()
{
foreach (var num in numArray) {}
return 0;
}
[Benchmark]
public long BenchDo_Array()
{
var i = 0;
while (i <= numArray.Length - 1)
{
i++;
}
return 0;
}
[Benchmark]
public long BenchDoWhile_Array()
{
var i = 0;
do
{
i++;
}
while (i <= numArray.Length - 1);
return 0;
}
#endregion
#region List
[Benchmark]
public long BenchFor_List()
{
for (var i = 0; i <= numList.Count - 1; i++) {}
return 0;
}
[Benchmark]
public long BenchForEach_List()
{
foreach (var num in numList) {}
return 0;
}
[Benchmark]
public long BenchDo_List()
{
var i = 0;
while (i <= numList.Count - 1)
{
i++;
}
return 0;
}
[Benchmark]
public long BenchDoWhile_List()
{
var i = 0;
do
{
i++;
}
while (i <= numList.Count - 1);
return 0;
}
#endregion
#region ArrayWithCalc
[Benchmark]
public long BenchForWithCalc_Array()
{
var total = 0;
for (var i = 0; i <= numArray.Length - 1; i++)
{
if (i % 2 == 0)
total += numArray[i];
}
return total;
}
[Benchmark]
public long BenchForEachWithCalc_Array()
{
var total = 0;
foreach (var num in numArray)
{
if (num % 2 == 0)
total += num;
}
return total;
}
[Benchmark]
public long BenchDoWithCalc_Array()
{
var i = 0;
var total = 0;
while (i <= numArray.Length - 1)
{
if (i % 2 == 0)
total += numArray[i];
i++;
}
return total;
}
[Benchmark]
public long BenchDoWhileWithCalc_Array()
{
var i = 0;
var total = 0;
do
{
if (i % 2 == 0)
total += numArray[i];
i++;
}
while (i <= numArray.Length - 1);
return total;
}
[Benchmark]
public long BenchLINQQuery_Array()
{
var total = (
from x in numArray
where x % 2 == 0
select (long)x
).Sum();
return total;
}
[Benchmark]
public long BenchLINQMethod_Array()
{
var total = numArray
.Where(x => x % 2 == 0)
.Sum(x => (long)x);
return total;
}
#endregion
#region ListWithCalc
[Benchmark]
public long BenchForWithCalc_List()
{
var total = 0;
for (var i = 0; i <= numList.Count - 1; i++)
{
if (i % 2 == 0)
total += numList[i];
}
return total;
}
[Benchmark]
public long BenchForEachWithCalc_List()
{
var total = 0;
foreach (var num in numList)
{
if (num % 2 == 0)
total += num;
}
return total;
}
[Benchmark]
public long BenchDoWithCalc_List()
{
var i = 0;
var total = 0;
while (i <= numList.Count - 1)
{
if (i % 2 == 0)
total += numList[i];
i++;
}
return total;
}
[Benchmark]
public long BenchDoWhileWithCalc_List()
{
var i = 0;
var total = 0;
do
{
if (i % 2 == 0)
total += numList[i];
i++;
}
while (i <= numList.Count - 1);
return total;
}
[Benchmark]
public long BenchLINQQuery_List()
{
var total = (
from x in numList
where x % 2 == 0
select (long)x
).Sum();
return total;
}
[Benchmark]
public long BenchLINQMethod_List()
{
var total = numList
.Where(x => x % 2 == 0)
.Sum(x => (long)x);
return total;
}
#endregion
}
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<LoopBenchmarkTest>();
}
}
}