<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div><br></div><blockquote type="cite"><div><div><br class=""></div>If by no brainer you mean the performance of __sort-key__ is always better of __lt__</div></blockquote><div><br></div><div>No. By no-brainer I meant that IF there is a __sort_key__ defined, then it should be used for sorting, regardless of whether __lt__ is also defined. (min and max should probably prefer <span style="background-color:rgba(255,255,255,0)"> __lt__)</span></div><div><br></div><blockquote type="cite"><div>I will wask for a proof in the form of benchmarks with enough use-case coverage.</div></blockquote><div><br></div><div>Indeed — I was surprised that it helped so much, and didn’t seem to hurt for the one example.</div><div><br></div><div>But the greater concern is that this will effect every sort (that doesn’t provide a key function) so if there is any noticeable performance hit, that probably kills the idea.</div><div><br></div><div>And the most risky example is lists of ints or floats — which are very fast to compare. So adding a method lookup could be a big impact.</div><div><br></div><div>I’m not sure how to benchmark that without hacking the sorting C code though.</div><div><br></div><div>I’d still love to know if my benchmark attempt was at all correct for custom classes in any case.</div><div><br></div><div>-CHB</div><div><br></div><div><br></div><div><br></div><br><blockquote type="cite"><div><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><div class=""><br class=""></div><div class="">def outer_key(item):</div><div class="">    return item.key()</div></div><div class=""><br class=""></div><div class="">so we get a function lookup each time it's used.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Did I make a mistake? is that lookup somehow cached?</div><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class="">In [36]: run sort_key_test.py</font></div><div class=""><font face="monospace, monospace" class="">10000</font></div><div class=""><font face="monospace, monospace" class="">key       0.012529s  10000 calls</font></div><div class=""><font face="monospace, monospace" class="">outer_key 0.012139s  10000 calls</font></div><div class=""><font face="monospace, monospace" class="">lt        0.048057s 119877 calls</font></div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">Also, I tried making a "simpler" __lt__ method:</div><div class=""><br class=""></div><div class=""><font face="monospace, monospace" class="">return (self.value1, self.value2) < (other.value1, other.value2)</font></div></div></blockquote><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">but it was bit slower than the previous one -- interesting.</div></div></blockquote><div><br class=""></div><div>This is more expensive to execute then my version for 2 reasons.</div><div>1) my __lt__ did not need to create any tuples.</div><div>2) my __lt__ can exit after only looking at the value1's</div><div class=""><br class=""></div><blockquote type="cite" class=""><div dir="ltr" class=""><div class=""><br class=""></div><div class="">Then I tried a simpler (but probably common) simple attribute sort:</div><div class=""><br class=""></div><font face="monospace, monospace" class="">    def __lt__(self, other):<br class="">        global lt_calls<br class="">        lt_calls += 1<br class=""><br class="">        return self.value1 < other.value1<br class=""><br class="">    def key(self):<br class="">        global key_calls<br class="">        key_calls += 1<br class=""><br class="">        return self.value1</font><div class=""><br class=""></div><div class="">And that results in about a 6X speedup</div><div class=""><br class=""></div><font face="monospace, monospace" class="">In [42]: run sort_key_test.py<br class="">10000<br class="">key       0.005157s  10000 calls<br class="">outer_key 0.007000s  10000 calls<br class="">lt        0.041454s 119877 calls<br class="">time ratio: 5.922036784741144</font><div class=""><br class=""></div><div class=""><br class=""></div><div class="">And, interestingly (t me!) there is even a performance gain for only  a 10 item list! (1.5X or so, but still)</div></div></blockquote><div><br class=""></div><div>My guess is that this is because the __lt__ test on simple types is very fast in python.</div><br class=""></div><div>Barry</div><div><br class=""></div><br class=""></blockquote><blockquote type="cite"><div><span>_______________________________________________</span><br><span>Python-ideas mailing list</span><br><span><a href="mailto:Python-ideas@python.org">Python-ideas@python.org</a></span><br><span><a href="https://mail.python.org/mailman/listinfo/python-ideas">https://mail.python.org/mailman/listinfo/python-ideas</a></span><br><span>Code of Conduct: <a href="http://python.org/psf/codeofconduct/">http://python.org/psf/codeofconduct/</a></span><br></div></blockquote></body></html>