> On 5 Dec 2017, at 01:06, Chris Barker <chris.bar...@noaa.gov> wrote:
> 
> wow! a few time zones (and a day job) really make a difference to taking part 
> in a discussion :-)
> 
> This could be a good idea -- just putting it here for the record as it's 
> mentioned elsewhere.
> 
> I can't think of a way to profile this easily -- we know that having a key 
> function can be helpful, but that doesn't take into account the extra method 
> lookup -- maybe a key function that involves a method lookup??
> 
> If it defines both, it isn't clear which will be used for sorting.
> Should __lt__ take priority, or __key__? Whichever we choose, somebody
> is going to be upset and confused by the choice.
> 
> __sort_key__ would take priority -- that is a no brainer, it's the sort key, 
> it's used for sorting. And __lt__ giving a different result is no more 
> surprising, and probably less surprising, than total ordering being violated 
> in  any other way.

If by no brainer you mean the performance of __sort-key__ is always better of 
__lt__ then I will wask for a proof in the form of benchmarks with enough 
use-case coverage.

> [I got very similar results as Barry with his version: about 5X faster with 
> the key function]
> 
> def outer_key(item):
>     return item.key()
> 
> so we get a function lookup each time it's used.
> 
> However, I'm confused by the results -- essentially NO Change. That extra 
> method lookup is coming essentially for free. And this example is using a 
> tuple as the key, so not the very cheapest possible to sort key.
> 
> Did I make a mistake? is that lookup somehow cached?
> 
> In [36]: run sort_key_test.py
> 10000
> key       0.012529s  10000 calls
> outer_key 0.012139s  10000 calls
> lt        0.048057s 119877 calls
> 
> each run gives different results, but the lt method is always on order of 5X 
> slower for this size list. Sometimes out_key is faster, mostly a bit slower, 
> than key.
> 
> Also, I tried making a "simpler" __lt__ method:
> 
> return (self.value1, self.value2) < (other.value1, other.value2)
> 
> but it was bit slower than the previous one -- interesting.

This is more expensive to execute then my version for 2 reasons.
1) my __lt__ did not need to create any tuples.
2) my __lt__ can exit after only looking at the value1's

> 
> Then I tried a simpler (but probably common) simple attribute sort:
> 
>     def __lt__(self, other):
>         global lt_calls
>         lt_calls += 1
> 
>         return self.value1 < other.value1
> 
>     def key(self):
>         global key_calls
>         key_calls += 1
> 
>         return self.value1
> 
> And that results in about a 6X speedup
> 
> In [42]: run sort_key_test.py
> 10000
> key       0.005157s  10000 calls
> outer_key 0.007000s  10000 calls
> lt        0.041454s 119877 calls
> time ratio: 5.922036784741144
> 
> 
> And, interestingly (t me!) there is even a performance gain for only  a 10 
> item list! (1.5X or so, but still)

My guess is that this is because the __lt__ test on simple types is very fast 
in python.

Barry


_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to