Skip to content

Instantly share code, notes, and snippets.

@phil-scott-78
Created May 21, 2016 17:46
Show Gist options
  • Save phil-scott-78/90c17ce95e2fb2fe834bdb177caf2531 to your computer and use it in GitHub Desktop.
Save phil-scott-78/90c17ce95e2fb2fe834bdb177caf2531 to your computer and use it in GitHub Desktop.
Updating in a loop benchmarks
using System.Linq;
using System.Threading.Tasks;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Columns;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Running;
namespace ParallelForEachUpdateBenchmark
{
public class Program
{
public static void Main(string[] args)
{
var config = ManualConfig.Create(DefaultConfig.Instance);
// uncomment code below to faster results, but at the cost of accuracy
/*
config.Add(Job.Default
.WithLaunchCount(1) // benchmark process will be launched only once
.WithIterationTime(100) // 100ms per iteration
.WithWarmupCount(3) // 3 warmup iteration
.WithTargetCount(3) // 3 target iteration
);
*/
config.Add(StatisticColumn.Max);
// MemoryDiagnoser and the parallel library combined withe the default job results in the some
// super long running benchmarks. Bewarned
// config.Add(new MemoryDiagnoser());
BenchmarkRunner.Run<UpdateBenchmark>(config);
}
}
public class UpdateBenchmark
{
[Params(
1000,
10000,
100000,
1000000)]
public int BatchSize { get; set; }
private MyData[] _data;
[Setup]
public void SetupData()
{
_data = new MyData[BatchSize];
for (var i = 0; i < BatchSize; i++)
{
_data[i] = new MyData();
}
}
[Benchmark]
public void ParallelUpdate()
{
Parallel.ForEach(_data, i => i.Success = true);
}
[Benchmark]
public void Linq()
{
_data.ToList().ForEach(i => i.Success = true);
}
[Benchmark]
public void ForEach()
{
foreach (var myData in _data)
{
myData.Success = true;
}
}
[Benchmark(Baseline = true)]
public void ForLoop()
{
for (var i = 0; i < _data.Length; i++)
{
_data[i].Success = true;
}
}
}
public class MyData
{
public string A { get; set; } = "Foo";
public string B { get; set; } = "Bar";
public bool Success { get; set; }
}
}
@mattwarren
Copy link

Too many variables and external things going on with that little one line of code for it to give good numbers consistently so I'd be hard pressed to call this a true benchmark of one algorithm vs another.

Agree, BenchmarkDotNet doesn't help as much for "large" benchmarks, with lots of variations run-to-run, it's sweet spot is micro-benchmarks.

But that's what I wanted my team to be thinking about - there is "stuff" the runtime needs to do behind the scenes that has costs, and in this case pretty significant costs compared to the cheapness of a good ol' for loop.

That's a good aim, I hope you managed to get that across!!

But there are many out there that are going to see that method and think "it is in the framework, so it must be there for a reason and that reason almost certainly is performance" so I wanted to nudge people to start thinking outside of that world view.

Likewise, that's what I'm trying to do with BenchmarkDotNet, i.e. give people tools to figure this out!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment