Type converter is still faster than dictionary cached LCG (without overflow problem solved) and I'm not even caching the type converter yet... The LCG solution does handle the overflow condition gracefully and I don't fully understand how it isn't overflowing, can you explain how what you are doing doesn't fail when converting int.MaxValue to a byte?
Also, how do you guys handle multi-key dictionaries typically? I have a way but am curious how you usually do it. On Mar 6, 10:02 am, Simone Busoli <[email protected]> wrote: > Try caching the LCG comparer, you'll be surprised. > > > > On Fri, Mar 6, 2009 at 16:46, webpaul <[email protected]> wrote: > > > This one takes 1000ms vs 6500ms but it handles one of the types being > > an overflow for the other. I couldn't find a way to detect if there > > will be an overflow for a specific value without actually catching the > > overflow exception which makes this take much longer. Any ideas? > > > class Program > > { > > static void Main(string[] args) > > { > > RunComparisons(CreateComparerLCG); > > RunComparisons(CreateComparerTypeConverter); > > } > > > //Comparison types > > > private static Func<object, object, bool> > > CreateComparerTypeConverter(Type firstType, Type secondType) > > { > > if (firstType == secondType) > > return Equals; > > > TypeConverter converterFirstType = > > TypeDescriptor.GetConverter(firstType); > > TypeConverter converterSecondType = > > TypeDescriptor.GetConverter(secondType); > > > return delegate(object first, object second) > > { > > try > > { > > return object.Equals( > > first, > > converterFirstType.ConvertTo(second, > > firstType) > > ); > > } > > catch (OverflowException) > > { > > return object.Equals( > > second, > > converterSecondType.ConvertTo(first, > > secondType) > > ); > > } > > }; > > } > > > private static Func<object, object, bool> CreateComparerLCG > > (Type firstType, Type secondType) > > { > > if (firstType == secondType) > > return Equals; > > > var firstParameter = Expression.Parameter(typeof(object), > > "first"); > > var secondParameter = Expression.Parameter(typeof(object), > > "second"); > > > var equalExpression = Expression.Equal(Expression.Convert > > (firstParameter, firstType), > > Expression.Convert(Expression.Convert(secondParameter, > > secondType), firstType)); > > > return Expression.Lambda<Func<object, object, bool>> > > (equalExpression, firstParameter, secondParameter).Compile(); > > } > > > private static void RunComparisons(Func<Type, Type, > > Func<object, object, bool>> createComparer) > > { > > List<Comparison> comparisonsToMake = new List<Comparison> > > { > > new Comparison { item = (byte)1, otherItem = (int)1 }, > > new Comparison { item = (int)1, otherItem = (long)1 }, > > new Comparison { item = (long)1, otherItem = (float) > > 1 }, > > new Comparison { item = (float)1, otherItem = (double) > > 1 }, > > new Comparison { item = (byte)byte.MaxValue, otherItem > > = (int)int.MaxValue, expectedValue = false }, > > }; > > > Program program = new Program(); > > > Stopwatch watch = new Stopwatch(); > > watch.Start(); > > for (int i = 0; i < 10000; i++) > > { > > foreach (var comparison in comparisonsToMake) > > { > > if (program.Compare(comparison, createComparer) != > > comparison.expectedValue) > > throw new ApplicationException("Comparison > > didn't work"); > > } > > }; > > watch.Stop(); > > Console.WriteLine("All comparisons took " + > > watch.ElapsedMilliseconds + "ms"); > > } > > > private class Comparison > > { > > public object item; > > public object otherItem; > > public bool expectedValue = true; > > } > > > private bool Compare(Comparison comparison, Func<Type, Type, > > Func<object, object, bool>> createComparer) > > { > > object item = comparison.item; > > object otherItem = comparison.otherItem; > > > if (item == null | otherItem == null) > > return item == null & otherItem == null; > > > var equalityComparer = createComparer(item.GetType(), > > otherItem.GetType()); > > > return equalityComparer(item, otherItem); > > } > > > } > > > On Mar 6, 9:23 am, webpaul <[email protected]> wrote: > > > This does it in 93ms vs. 6500ms on my box, could be improved with a > > > Dictionary as well. Also, it always converts to the first type so if > > > you compare byte.MaxValue with int.MaxValue you get an exception. It > > > should convert to the largest type so I'll see what I can do on that > > > as well. > > > > private static Func<object, object, bool> > > > CreateComparerTypeConverter(Type firstType, Type secondType) > > > { > > > if (firstType == secondType) > > > return Equals; > > > > TypeConverter converterFirstType = > > > TypeDescriptor.GetConverter(firstType); > > > TypeConverter converterSecondType = > > > TypeDescriptor.GetConverter(firstType); > > > > return delegate(object first, object second) > > > { > > > return > > > object.Equals( > > > converterFirstType.ConvertTo(first, > > > firstType), > > > converterFirstType.ConvertTo( > > > converterSecondType.ConvertTo(second, > > > secondType), > > > firstType > > > ) > > > ) > > > ; > > > }; > > > } > > > > On Mar 6, 9:10 am, webpaul <[email protected]> wrote: > > > > > It's pretty slow as is - takes 6.5 seconds for 10K iterations. I'm > > > > going to try it a few different ways and see which is fastest. > > > > > class Program > > > > { > > > > static void Main(string[] args) > > > > { > > > > RunComparisons(CreateComparerLCG); > > > > } > > > > > //Comparison types > > > > > private static Func<object, object, bool> CreateComparerLCG > > > > (Type firstType, Type secondType) > > > > { > > > > if (firstType == secondType) > > > > return Equals; > > > > > var firstParameter = Expression.Parameter(typeof(object), > > > > "first"); > > > > var secondParameter = Expression.Parameter(typeof(object), > > > > "second"); > > > > > var equalExpression = Expression.Equal(Expression.Convert > > > > (firstParameter, firstType), > > > > Expression.Convert(Expression.Convert(secondParameter, > > > > secondType), firstType)); > > > > > return Expression.Lambda<Func<object, object, bool>> > > > > (equalExpression, firstParameter, secondParameter).Compile(); > > > > } > > > > > private static void RunComparisons(Func<Type, Type, > > > > Func<object, object, bool>> createComparer) > > > > { > > > > List<Comparison> comparisonsToMake = new List<Comparison> > > > > { > > > > new Comparison { item = (byte)1, otherItem = (int)1 }, > > > > new Comparison { item = (int)1, otherItem = (long)1 }, > > > > new Comparison { item = (long)1, otherItem = (float) > > > > 1 }, > > > > new Comparison { item = (float)1, otherItem = (double) > > > > 1 }, > > > > }; > > > > > Program program = new Program(); > > > > > Stopwatch watch = new Stopwatch(); > > > > watch.Start(); > > > > for (int i = 0; i < 10000; i++) > > > > { > > > > foreach (var comparison in comparisonsToMake) > > > > { > > > > if (!program.Compare(comparison, createComparer)) > > > > throw new ApplicationException("Comparison > > > > didn't work"); > > > > } > > > > }; > > > > watch.Stop(); > > > > Console.WriteLine("All comparisons took " + > > > > watch.ElapsedMilliseconds + "ms"); > > > > } > > > > > private class Comparison > > > > { > > > > public object item; > > > > public object otherItem; > > > > } > > > > > private bool Compare(Comparison comparison, Func<Type, Type, > > > > Func<object, object, bool>> createComparer) > > > > { > > > > object item = comparison.item; > > > > object otherItem = comparison.otherItem; > > > > > if (item == null | otherItem == null) > > > > return item == null & otherItem == null; > > > > > var equalityComparer = createComparer(item.GetType(), > > > > otherItem.GetType()); > > > > > return equalityComparer(item, otherItem); > > > > } > > > > > } > > > > > On Mar 5, 11:46 pm, Ayende Rahien <[email protected]> wrote: > > > > > > Stopwatch.StartNew > > > > > Please measure. > > > > > > On Thu, Mar 5, 2009 at 7:56 PM, webpaul <[email protected]> wrote: > > > > > > > What kind of performance gain is there to what you did compared to > > > > > > using a TypeConverter on both objects, then a final comparison of > > the > > > > > > result? Curious if you have looked at that before. > > > > > > > That is creating an expression for each row and compiling it for > > each > > > > > > row, right? I'm guessing the main factor here is performance so if > > it > > > > > > was that big of a concern I wonder if you wouldn't want to make a > > > > > > dictionary of them for the unique types encountered, especially > > since > > > > > > most rows are going to have the same columns. > > > > > > > I think I'm going to work up an example app with a few of these > > > > > > methods on lots of rows, to try some of these out and see the > > ... > > read more »- Hide quoted text - > > - Show quoted text - --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Rhino Tools Dev" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/rhino-tools-dev?hl=en -~----------~----~----~----~------~----~------~--~---
