Uploaded RowComparePerformanceFix.patch, previous code did not complete in under 500ms, took 1200ms (on my computer). Just did multi keys as string concatenation since I never heard any feedback on how you want to handle multi key dictionaries.
On Mar 8, 7:19 pm, webpaul <[email protected]> wrote: > Even the uncached type converter is faster than cached LCG, 11 seconds > instead of 13. Perhaps the LINQ expression implementation for > conversion is more expensive than the standard type converter. > > 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); > > int firstTypeSize = > System.Runtime.InteropServices.Marshal.SizeOf(firstType); > int secondTypeSize = > System.Runtime.InteropServices.Marshal.SizeOf(secondType); > > if (secondTypeSize >= firstTypeSize) > { > return delegate(object first, object second) > { > return object.Equals( > second, > converterSecondType.ConvertTo(first, > secondType) > ); > }; > > } > else > { > return delegate(object first, object second) > { > return object.Equals( > first, > converterFirstType.ConvertTo(second, > firstType) > ); > }; > } > > } > > On Mar 8, 7:15 pm, webpaul <[email protected]> wrote: > > > > > Found a way to compare the type sizes. Using this method for previous > > examples, it returns in 37ms which would seem to be faster than the > > LCG. I wanted to rule out a larger startup time for LCG as opposed to > > execution time, so for 1 million rows the cached LCG takes 13 seconds > > and the type converter method below takes 3 seconds. > > > Separate caches of course. :) > > > private static Func<object, object, bool> > > CreateComparerTypeConverterCached(Type firstType, Type secondType) > > { > > if (firstType == secondType) > > return Equals; > > > Func<object, object, bool> compareExpression = null; > > CacheKey key = new CacheKey { FirstType = firstType, > > SecondType = secondType }; > > if (!comparerCacheClass.TryGetValue(key, out > > compareExpression)) > > { > > TypeConverter converterFirstType = > > TypeDescriptor.GetConverter(firstType); > > TypeConverter converterSecondType = > > TypeDescriptor.GetConverter(secondType); > > > int firstTypeSize = > > System.Runtime.InteropServices.Marshal.SizeOf(firstType); > > int secondTypeSize = > > System.Runtime.InteropServices.Marshal.SizeOf(secondType); > > > if (secondTypeSize >= firstTypeSize) > > { > > compareExpression = delegate(object first, object > > second) > > { > > return object.Equals( > > second, > > converterSecondType.ConvertTo(first, > > secondType) > > ); > > }; > > > } > > else > > { > > compareExpression = delegate(object first, object > > second) > > { > > return object.Equals( > > first, > > converterFirstType.ConvertTo(second, > > firstType) > > ); > > }; > > } > > > comparerCacheClass.Add(key, compareExpression); > > } > > > return compareExpression; > > } > > > On Mar 7, 12:34 pm, webpaul <[email protected]> wrote: > > > > Doh! Nice catch. > > > > Looks like it is really 800ms, the try/catch is a killer because it's > > > in the delegate so caching it doesn't give a big benefit. If there was > > > an unchecked type converter or some way to tell which type was bigger > > > so I could always cast to that then I suspect the type converter would > > > be better. But as-is (including the overflow scenario) the cached LCG > > > is the best. > > > > On Mar 7, 10:29 am, Simone Busoli <[email protected]> wrote: > > > > > Did you realize that you're using a shared cache, which is already > > > > filled > > > > with delegates when you run the fourth step? > > > > > On Sat, Mar 7, 2009 at 16:45, webpaul <[email protected]> wrote: > > > > > > Until I know how you want to handle multi key dictionaries in your > > > > > code base I'm not going to submit a patch. Below is how I did it with > > > > > a class I usually use for that, more details at: > > > > >http://www.codeproject.com/KB/recipes/ClassKey.aspx > > > > > > If anyone is interested, the LINQ expressions used in the LCG have a > > > > > checked/unchecked version which is why it didn't have the overflow > > > > > issue. As far as I can tell type converters don't have that feature > > > > > and using an unchecked block doesn't stop it from throwing an > > > > > exception. When the type converters are cached they are better than > > > > > the cached LCG unless I'm doing something wrong here. > > > > > > Performance from worst to best, with the original test rows plus one > > > > > more for overflow condition: > > > > > > 10K iterations * 5 tests per iteration: > > > > > > LCG compiled each time - 8043ms > > > > > TypeConverter with try/catch : 869ms > > > > > LCG cached: 143ms > > > > > TypeConverter without try/catch (exception on overflow): 82ms > > > > > Type converter with try/catch cached: 23ms > > > > > > class Program > > > > > { > > > > > static void Main(string[] args) > > > > > { > > > > > RunComparisons(CreateComparerLCG); > > > > > RunComparisons(CreateComparerTypeConverter); > > > > > RunComparisons(CreateComparerLCGCachedClass); > > > > > RunComparisons(CreateComparerTypeConverterCached); > > > > > } > > > > > > //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 class CacheKey : ClassKey<CacheKey> > > > > > { > > > > > public Type FirstType = null; > > > > > public Type SecondType = null; > > > > > > public override object[] GetKeyValues() > > > > > { > > > > > return new object[] { FirstType, SecondType }; > > > > > } > > > > > } > > > > > > private class ComparerCacheClass : Dictionary<CacheKey, > > > > > Func<object, object, bool>> { } > > > > > private static readonly ComparerCacheClass comparerCacheClass > > > > > = new ComparerCacheClass(); > > > > > private static Func<object, object, bool> > > > > > CreateComparerLCGCachedClass(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), > > ... > > 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 -~----------~----~----~----~------~----~------~--~---
