Skip to content

Instantly share code, notes, and snippets.

@litera
Created November 29, 2011 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save litera/1403144 to your computer and use it in GitHub Desktop.
Save litera/1403144 to your computer and use it in GitHub Desktop.
Console application conparimg Lambda implementation performance
public class Program
{
private static Random rnd = new Random();
private const int RangeLength = 365;
private const int RangeCount = 1;
private const int MaxRangeLength = 100;
private const int IterationCount = 1000000;
private const int RepeatCount = 5;
private static readonly DateTime RangeStart = new DateTime(2012, 1, 1);
private static readonly DateTime RangeEnd = RangeStart.AddDays(RangeLength);
static void Main(string[] args)
{
IList<RangeItem> items = GenerateRanges().ToList();
RangeLookupBase<RangeItem> iter = new IterationRangeLookup<RangeItem>(RangeStart, RangeEnd, items);
RangeLookupBase<RangeItem> buil = new BuilderLambdaRangeLookup<RangeItem>(RangeStart, RangeEnd, items);
RangeLookupBase<RangeItem> norm = new NormalLambdaRangeLookup<RangeItem>(RangeStart, RangeEnd, items);
RangeLookupBase<RangeItem> prop = new ProperyClosureLambdaRangeLookup<RangeItem>(RangeStart, RangeStart, items);
RangeLookupBase<RangeItem> fiel = new FieldClosureLambdaRangeLookup<RangeItem>(RangeStart, RangeStart, items);
RangeLookupBase<RangeItem> cust = new CustomClosureLambdaRangeLookup<RangeItem>(RangeStart, RangeStart, items);
Console.Write("\nForeach loop".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(iter));
}
Console.Write("\nFree variable".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(norm));
}
Console.Write("\nClosure using property".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(prop));
}
Console.Write("\nClosure using field".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(fiel));
}
Console.Write("\nDouble method closure".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(cust));
}
Console.Write("\nPredicate builder".PadRight(25));
for (int i = 0; i < RepeatCount; i++)
{
Console.Write(" {0}ms", Execute(buil));
}
Console.WriteLine("");
}
#region Execute
private static long Execute<TItem>(RangeLookupBase<TItem> lookup)
where TItem : RangeItem
{
IList<TItem> result;
Stopwatch timer = new Stopwatch();
timer.Start();
for (int i = 0; i < IterationCount; i++)
{
result = lookup.GetDayDataList(RangeStart.AddDays(rnd.Next(RangeLength)));
}
timer.Stop();
return timer.ElapsedMilliseconds;
}
#endregion
#region GenerateRanges
/// <summary>
/// Generates an arbitarry number of random ranges.
/// </summary>
/// <returns>Returns a set of randomly generated ranges.</returns>
private static IEnumerable<RangeItem> GenerateRanges()
{
int startOffset, endOffset;
for (int i = 0; i < RangeCount; i++)
{
startOffset = rnd.Next(RangeLength - 10);
endOffset = startOffset + 1 + rnd.Next(Math.Min(RangeLength - startOffset, MaxRangeLength));
yield return new RangeItem(
i,
RangeStart.AddDays(startOffset),
RangeStart.AddDays(endOffset)
);
}
}
#endregion
}
#region Utility classes
#region RangeItem
/// <summary>
/// A simple date range related entity.
/// </summary>
public class RangeItem
{
public int Id { get; private set; }
public DateTime Start { get; private set; }
public DateTime End { get; private set; }
public int Length
{
get { return (int)(this.End - this.Start).TotalDays; }
}
public RangeItem(DateTime start, DateTime end) : this(-1, start, end) { }
public RangeItem(int id, DateTime start, DateTime end)
{
this.Id = id;
this.Start = start;
this.End = end;
}
/// <summary>
/// Checks whether provided day is within date range of this instance.
/// </summary>
/// <param name="day">
/// <see cref="DateTime">DateTime</see> instance to check.
/// </param>
public bool IsDayWithinRange(DateTime day)
{
return day >= this.Start && day < this.End;
}
}
#endregion
#region RangeLookupBase
public abstract class RangeLookupBase<TItem> : RangeItem
where TItem : RangeItem
{
protected IEnumerable<TItem> items = null;
protected RangeLookupBase(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end)
{
this.items = items;
}
public abstract IEnumerable<TItem> GetDayData(DateTime day);
public IList<TItem> GetDayDataList(DateTime day)
{
return this.GetDayData(day).ToList();
}
}
#endregion
#region IterationRangeLookup
public class IterationRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
public IterationRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
// does nothing else
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
foreach (TItem item in this.items)
{
if (item.IsDayWithinRange(day))
{
yield return item;
}
}
}
}
#endregion
#region BuilderLambdaRangeLookup
public class BuilderLambdaRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
public BuilderLambdaRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
// does nothing else
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
Func<DateTime, Func<TItem, bool>> getPredicate = d => i => i.IsDayWithinRange(d);
return this.items.Where(getPredicate.Invoke(day));
}
}
#endregion
#region NormalLambdaRangeLookup
public class NormalLambdaRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
public NormalLambdaRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
// does nothing else
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
Func<TItem, bool> predicate = i => i.IsDayWithinRange(day);
return this.items.Where(predicate);
}
}
#endregion
#region ProperyClosureLambdaRangeLookup
public class ProperyClosureLambdaRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
private class Closure<TObject, TVariable>
{
public TVariable Variable { get; set; }
public Func<TObject, bool> Predicate { get; set; }
}
private Closure<TItem, DateTime> closure;
public ProperyClosureLambdaRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
this.closure = new Closure<TItem, DateTime>();
closure.Predicate = i => i.IsDayWithinRange(closure.Variable);
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
this.closure.Variable = day;
return this.items.Where(this.closure.Predicate);
}
}
#endregion
#region FieldClosureLambdaRangeLookup
public class FieldClosureLambdaRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
private class Closure<TObject, TVariable>
{
public TVariable Variable;
public Func<TObject, bool> Predicate;
}
private Closure<TItem, DateTime> closure;
public FieldClosureLambdaRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
this.closure = new Closure<TItem, DateTime>();
this.closure.Predicate = i => i.IsDayWithinRange(this.closure.Variable);
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
this.closure.Variable = day;
return this.items.Where(this.closure.Predicate);
}
}
#endregion
#region CustomClosureLambdaRangeLookup
public class CustomClosureLambdaRangeLookup<TItem> : RangeLookupBase<TItem>
where TItem : RangeItem
{
public class Closure<TObject, TVariable>
{
public TVariable Variable;
public Func<Closure<TObject, TVariable>, TObject, bool> OpenPredicate;
public bool ClosedPredicate(TObject o)
{
return OpenPredicate(this, o);
}
}
private Closure<TItem, DateTime> closure;
public CustomClosureLambdaRangeLookup(DateTime start, DateTime end, IEnumerable<TItem> items)
: base(start, end, items)
{
this.closure = new Closure<TItem, DateTime>() {
OpenPredicate = (closure, item) => item.IsDayWithinRange(closure.Variable)
};
}
public override IEnumerable<TItem> GetDayData(DateTime day)
{
this.closure.Variable = day;
return this.items.Where(this.closure.ClosedPredicate);
}
}
#endregion
#endregion
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment