TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Python: Faster Way

144 pointsby kozlovskyover 10 years ago

20 comments

perlgeekover 10 years ago
And this, ladies and gentlemen, is how you <i>not</i> make speed comparisons.<p>#7 surprised me: why would &#x27;if a:&#x27; be slower than &#x27;if not a:&#x27;? So I ran the code myself, and ran it a few times. And lo and behold, the third digit varies greatly between runs. And the timing between the first and second variant only differ in the third digit.<p>I ran the first and second variant ten times, and got these values:<p>first: 0.138 +- 0.05<p>second: 0.137 +- 0.04<p>So there is no significant difference in my timings, though individual runs differed as much as 0.132 vs. 0.150.<p>Though kudos for providing the full code and the raw output. It made quite easy to reproduce!<p>These are the timings I measured, in octave&#x2F;matlab syntax:<p><pre><code> t1 = [0.132781028748, 0.140866041183, 0.13587808609, 0.138177871704, 0.137129068375, 0.150414943695, 0.138676166534, 0.137069940567, 0.13484787941, 0.136043071747]; mean(t1) std(t1) t2 = [ 0.134783983231, 0.143576860428, 0.138277769089, 0.142880916595, 0.140572071075, 0.136868000031, 0.131128787994, 0.134744167328, 0.132730007172, 0.137500047684]; mean(t2) std(t2)</code></pre>
评论 #8814432 未加载
评论 #8817811 未加载
评论 #8815387 未加载
jhggover 10 years ago
Examples b and c on test #6 is something you should NEVER do in Python. Using &quot;is&quot; checking for integers is a huge no-no, and will only work for smaller integers (I think between -5 and 256) that are cached by the interpreter. &quot;is&quot; does identity checking, not equality checking.<p><pre><code> &gt;&gt;&gt; a = 500 &gt;&gt;&gt; b = 500 &gt;&gt;&gt; a is b False &gt;&gt;&gt; a == b True &gt;&gt;&gt; a = 2 &gt;&gt;&gt; b = 2 &gt;&gt;&gt; a is b True &gt;&gt;&gt; a == b True</code></pre>
ayrxover 10 years ago
I honestly do not get the point of this page.<p>None of the time differences in all the test cases are significant at all. Concerning yourself with this is premature optimization of the highest level especially in a language like Python. One should definitely be more concerned about writing clearer and more idiomatic code.
评论 #8814032 未加载
评论 #8814145 未加载
评论 #8814238 未加载
评论 #8813983 未加载
评论 #8814185 未加载
TickleSteveover 10 years ago
Two points:<p>- The time differences displayed here are just not significant on a desktop OS such as Windows or Linux. Maybe Windows decided to swap or collect your email (or more likely virus check) as the test was running? The error bars on these numbers will make them insignificant.<p>- When using Python, readability&gt;&gt;performance. If you want performance, use C; don&#x27;t even try to optimise Python, its not worth the effort.
评论 #8815101 未加载
评论 #8815494 未加载
Tobuover 10 years ago
Those are the quirks of CPython 2.7. The best optimisation is to run with PyPy — those benchmarks run about 10 times faster.<p>After that, if you want to optimise, you need an applicative benchmark. A microbenchmark won&#x27;t work because type specialisation runs for (traces of) the program as a whole.
jevgeniover 10 years ago
This just feels like picking up pennies in front of a steam roller.
jwlover 10 years ago
Could someone please explain #Test 11. How is using %s instead of %d double as fast even though it is the same thing is being calculated? I always use %d because it seems like the prooper way to do it.
评论 #8814242 未加载
thuover 10 years ago
I met someone who was specifically using `dict()` instead of `{}` because, he told me, the CPython parser was much slower on the later than on the former and that it was noticeable on larger code base.<p>(That being said I think using Python should be about writing maintainable code, not about micro-optimization.<p>I don&#x27;t claim the purpose of that site is to push you to use those micro-optimizations, even if the title seems to suggest so. Including the disassembly makes for a nice visualization.)
评论 #8814470 未加载
chriswarboover 10 years ago
<p><pre><code> &gt;&gt;&gt; timeit(a, number=1000000) ... 0.102125167847 </code></pre> Measurements shouldn&#x27;t be quoted without some kind of range, confidence interval, error bar, etc.<p>I&#x27;ve not come across timeit before, but maybe they could learn a thing or two from systems like Criterion <a href="http://www.serpentine.com/criterion/" rel="nofollow">http:&#x2F;&#x2F;www.serpentine.com&#x2F;criterion&#x2F;</a>
Beltirasover 10 years ago
I found the most enlightening part being the module &#x27;dis&#x27; which I was totally oblivious of, but will partake of often from hereon in.
njharmanover 10 years ago
Profile dammit!<p>Things that improve by few tenths of a second in a million iterations are NOT WORTH YOUR TIME.
ssebastianjover 10 years ago
Make It Work -&gt; Make It Right -&gt; Make It Fast
TheLoneWolflingover 10 years ago
These all seem like simple peephole optimizations to me. So why doesn&#x27;t the Python compiler (and yes, Python has a compiler) do these optimizations?<p>(I am aware that some of these are not in fact equivalent, but at least some of them are)<p>On an unrelated note, the website would be easier to grok if it did diff-like highlighting of changed lines.
评论 #8814731 未加载
ww2over 10 years ago
Almost none of them are significant.
vanderZwanover 10 years ago
I&#x27;m more surprised that the disassemblies differ <i>at all</i> with half of these tests.
eveningcoffeeover 10 years ago
I am wondering what is exactly measured here (by timeit). For example for test 5, there is noticeable difference between timings of variants b and c despite them evaluating to the same list of instructions (and I did tests by myself).
评论 #8814276 未加载
评论 #8814280 未加载
nosefrogover 10 years ago
For the tests where the speed difference is significant, these are really areas where the python optimizer (I assume the bytecode compiler does some optimization?) needs to improve. Humans shouldn&#x27;t be concerned with such small differences in the literal representation of code.
im3w1lover 10 years ago
What&#x27;s up with test 11, variant 1 vs 3?
评论 #8814043 未加载
nichocharover 10 years ago
This is so easy and quick to read, yet very interesting. Good job and thanks for making it
jdimovover 10 years ago
Here are my annotations for how I&#x27;m reading these. Feel free to correct or update:<p>1. Faster to use dict literals than the `dict()` constructor<p>2. Faster to sort a list in-place than to use `sorted()`<p>3. Faster to use multiple assignment than multiple individual assignments<p>4. Faster to evaluate multiple individual conditions than a single multi-comparison condition<p>5. Faster to use idiomatic implied truth value than to compare to `True`<p>6. Faster to use `!=` than `is not`<p>7. Fastest way to check for empty list `a` is the idiomatic `if not a`<p>8. Fastest way to check that an object is not null is `if a`<p>9. `enumerate` is faster than doing it yourself<p>10. Constructing strings with `+=` is faster than string surgery<p>11. Fastest way to place a number in a string is &quot;%s&quot; (not &quot;%d&quot;)<p>12. For built-in types, using built-in functions (e.g. `len`) is faster than calling methods (e.g. `a.__len__`)<p>13. For built-in types, using built-in operators (e.g. `+`) is faster than calling methods (e.g. `a.__add__(b)`)<p>14. But for custom-defined classes, the opposite of #13 is true.<p>15. Adding up a bunch of numbers using `+` is faster than using `sum`<p>16. When initializing a large list, it is faster to use list comprehensions than to append each element individually<p>17. The fastest way to build a large dict is to use a dictionary comprehension<p>18. Same as #17<p>19. Not sure what the author is trying to demonstrate here. That `bool(a)` is faster when `a` is an empty list?<p>20. Faster to use implied truth value of an expression than to compare explicitly to `True` or `False`<p>21. The fastest way to refer to a list is to use the list literal (duh...)<p>22. It is faster to perform individual comparisons than to check for membership with `in`<p>23. Faster to `map` the `str` function to a list of values and join, than to manually build up the string. Also, when doing this, faster to use `xrange` than `range`<p>24. Faster to unpack than to access each list element individually. Also, as in #1, faster to use dict literal than the `dict()` constructor.<p>25. Faster to just return the boolean value of an expression than to check for it and then decide what to return.<p>26. Faster to give explicit values to keyword arguments than to expand a dict with kwargs.<p>27. To switch the values of `a` and `b`, it is faster to use a third variable than to do it in-place using unpacking.<p>28. Multiple assignment is faster than unpacking, which is faster than multiple individual assignments.<p>29. Fastest way to get integer part of a real is to use `math.floor`<p>30. Similar to #26 - it is faster to give explicit values to positional arguments than to expand a list of args.<p>31. Faster to access local vars than globals.<p>32. When trying to safely access a key in a dictionary, it is faster to use the idiomatic `D[k] if k in D` than to use the `get` method.
评论 #8814670 未加载
评论 #8814388 未加载
评论 #8817977 未加载