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
-~----------~----~----~----~------~----~------~--~---

Reply via email to