Skip to content

Instantly share code, notes, and snippets.

@justinvp
Created November 28, 2015 18:22
Show Gist options
  • Save justinvp/a09a27fb4560c8638d35 to your computer and use it in GitHub Desktop.
Save justinvp/a09a27fb4560c8638d35 to your computer and use it in GitHub Desktop.
KeyedCollection<TKey,TItem> equivalent microbenchmark (avoiding enumerator allocations when enumerating Items internally)
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
class Program
{
static void Main()
{
const int size = 100;
var before = new Before();
var after = new After();
AddItems(before, size);
AddItems(after, size);
var sw = new Stopwatch();
const int ITERS = 1000000;
while (true)
{
Console.Write("A:");
sw.Restart();
for (int i = 0; i < ITERS; i++)
{
before.Contains(int.MaxValue);
before.Contains(int.MaxValue);
before.Contains(int.MaxValue);
before.Contains(int.MaxValue);
before.Contains(int.MaxValue);
before.Contains(10);
before.Contains(10);
before.Contains(10);
before.Contains(10);
before.Contains(10);
}
var elapsedA = sw.Elapsed;
Console.WriteLine(elapsedA);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.Write("B:");
sw.Restart();
for (int i = 0; i < ITERS; i++)
{
after.Contains(int.MaxValue);
after.Contains(int.MaxValue);
after.Contains(int.MaxValue);
after.Contains(int.MaxValue);
after.Contains(int.MaxValue);
after.Contains(10);
after.Contains(10);
after.Contains(10);
after.Contains(10);
after.Contains(10);
}
var elapsedB = sw.Elapsed;
Console.WriteLine(elapsedB);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Console.WriteLine("A/B : {0}", elapsedA.TotalMilliseconds / elapsedB.TotalMilliseconds);
Console.WriteLine("B/A : {0}", elapsedB.TotalMilliseconds / elapsedA.TotalMilliseconds);
Console.WriteLine("(A-B)/A : {0}", Math.Abs((elapsedA.TotalMilliseconds - elapsedB.TotalMilliseconds) / elapsedA.TotalMilliseconds));
Console.WriteLine("(B-A)/B : {0}", Math.Abs((elapsedB.TotalMilliseconds - elapsedA.TotalMilliseconds) / elapsedB.TotalMilliseconds));
Console.WriteLine();
Console.ReadLine();
}
}
static void AddItems(ICollection<int> collection, int size)
{
for (int i = 1; i <= size; i++)
{
collection.Add(i);
}
}
}
class Before : Before<int, int>
{
protected override int GetKeyForItem(int item)
{
return item;
}
}
class After : After<int, int>
{
protected override int GetKeyForItem(int item)
{
return item;
}
}
abstract class Before<TKey, TItem> : Collection<TItem>
{
private readonly IEqualityComparer<TKey> _comparer = EqualityComparer<TKey>.Default;
public Before() { }
public bool Contains(TKey key)
{
if (key == null)
throw new ArgumentNullException("key");
foreach (TItem item in Items)
{
if (_comparer.Equals(GetKeyForItem(item), key))
return true;
}
return false;
}
protected abstract TKey GetKeyForItem(TItem item);
}
abstract class After<TKey, TItem> : Collection<TItem>
{
private readonly IEqualityComparer<TKey> _comparer = EqualityComparer<TKey>.Default;
public After() : base(new List<TItem>()) { }
new private List<TItem> Items
{
get { return (List<TItem>)base.Items; }
}
public bool Contains(TKey key)
{
if (key == null)
throw new ArgumentNullException("key");
foreach (TItem item in Items)
{
if (_comparer.Equals(GetKeyForItem(item), key))
return true;
}
return false;
}
protected abstract TKey GetKeyForItem(TItem item);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment