A Python Optimization Anecdote
tech.dropbox.com
tech.dropbox.com
I've been amazed at Java's speedup over multiple runs: dead-slow on startup, then improving rapidly over the next 10-20 runs, and even keeps improving slowly after that. It's a bit magical. Much (all?) of that JIT tech should be applicable to Python, I'd think.
BTW: link is to the comments, not the story
http://www.skymind.com/~ocrow/python_string/
It seemed like the concatenation was the primary bottleneck in this case.
Also, its worth noting that percentage gains on performance have huge cost savings on infrastructure at scale. That's why blogs like this are valuable because the user experience improves while the cost to provide it is reduced.
if x in WHITELIST
with if ((x >= '0' && x <= '9') ||
(x >= 'A' && x <= 'Z') ||
(x >= 'a' && x <= 'z'))
which I suspect would be much faster than any hash-table implementation. Also I believe that should work for UTF-8 as well as ascii. I realise that this makes it harder to expand the whitelist. I'm not very familiar with python, is there something similar that could be done? if ((x >= 'a' && x <= 'z') ||
(x >= 'A' && x <= 'Z') ||
(x >= '0' && x <= '9'))
As in a regular text file you're more likely to hit an alphanumerical character than a number. If the first OR statement is true, any good compiler will skip the next two clauses.(Although I'm not sure if lookup would be faster at all than a few comparisons, considering caches and everything, but this is not my domain.)
if: 1x
byte-based lookup: 0.83x
int-based lookup: 0.84x
bit-vector based lookup: 0.93x
http://pastebin.com/5twfXfEtThis has nothing to do with the compiler, it's part of the language specification. If your compiler doesn't comply with this, it's broken.
return (CHAR_MAP_ARRAY[c] = 'y')
Any UTF-8 start or follow byte shoudl be > 128 where there should always be values indicating false white_ranges = [('0', '9'), ('A', 'Z'), ('a', 'z')]
any([ord(low) <= ord(x) <= ord(high) for low, high in white_ranges])Then in your loop you're only making dict lookups.
If I were the guy, I'd first ensure the final escaped result is cached in a key-value store, then I'll check if this func is the real bottleneck. If so, I might also have tried accessing it's content as a byte array. Then, if the file is of Asian origin (ascii being very low minority), I'd bulk escape it with the "&#x%s;" trick. It is rare to have documents with even mix of ascii/latin and other glyph, so I makes sense to have two functions, like he did.
>Other “common wisdom”, like using locals instead of globals, yields relatively little gain.
this advice was typically more related to avoiding collisions with variable names, rather than performance?
Python has full dynamic scoping, which means that inside a function you can refer to any variables set in outer scopes. Because Python is a dynamic language, every time you refer to a variable, the Python interpreter looks for it in the local scope first, and then each enclosing scope until it hits the containing module. A local variable will always be found in the first iteration of that loop, a global variable will take at least two iterations.
You are describing lexical scope, not dynamic scope.
Besides, the general advice is not to avoid collisions (you use both namespaces and locality to resolve that) as the non local stuff here really has a reason to be global, but non local stuff has to survive concurrency. It is the case here as the things called really are constants.
Some best practices when optimizing CPython code:
* Re-evaluate your algorithm (an inefficient quicksort is still faster than an optimized bubblesort)
* Use Python functions and constructs implemented in C (ex. most builtins, list comprehensions)
* Move loops from outside functions to inside (function call overhead is high)
* Use try/except to handle uncommon cases rather than using conditional checks in a loop.
* Eliminate dots (attribute lookup) in tight loops (create a local alias if needed)
See also: http://wiki.python.org/moin/PythonSpeed/PerformanceTips
How about we stop painting pictures of languages from one specific difference.