Optimizations which made Python 3.6 faster than Python 3.5 [video]
pyvideo.org
pyvideo.org
One thing to keep in mind is that python 3 is still considerably slower than python 2 (edit) in some areas such as startup times while it has gotten faster in most other benchmarks.
> One thing to keep in mind is that python 3 is still considerably slower than python 2.
IIRC this statement started to shift ~3.4. There are still areas where 2.7 is faster, but it is more of a gray area than black and white like it used to be.
$ echo exit | time python2
gives an average time of 0.015s on my laptop, and $ echo exit | time python3
works out to about 0.039s. If you're spamming hundreds of processes from a looping shell script, the Python 3 overhead would probably start to grate. For anything manually launched, 40 milliseconds is still substantially close to instant.You should absorb the loop into a single python process that instead calls the original script as a library...
~ time python2 -c exit
real 0m0.014s
user 0m0.011s
sys 0m0.004s
vs. ~ time python3 -c exit
real 0m0.022s
user 0m0.018s
sys 0m0.004s
So for me it's more like an 8ms realtime difference, and four milliseconds are spent in the system either way.python2 seems to do about 700 system calls (!) to start up and exit immediately, including enumerating things like gtk-2 and wxwidgets, which boggles the mind, but it is what it is.
python3 seems to do about 470 system calls, much less but still bonkers to my mind. Also weird that they take the same ~4ms in the kernel given that python3 calls into the kernel so much less.
Thanks for including the syscall counts. I know they'd been working to reduce that, but I hadn't seen how much progress they'd made yet. Are most of those to malloc() and open()?
~ strace python2 -c exit 2>&1 | sort | grep "^[a-z_]*[(]" | sed -e "s/^\([a-z_]*\)[(].*/\1/" | uniq -c | sort -rn | head -n 8
199 open
98 read
94 fstat
92 stat
68 rt_sigaction
63 close
27 mmap
16 mprotect
Mostly stat, rt_sigaction, and read for python3: ~ strace python3 -c exit 2>&1 | sort | grep "^[a-z_]*[(]" | sed -e "s/^\([a-z_]*\)[(].*/\1/" | uniq -c | sort -rn | head -n 8
92 stat
68 rt_sigaction
57 read
54 fstat
35 open
35 close
28 mmap
24 lseek
Some of this might be noise though, it's possible that it has something to do with the installed packages, not sure exactly. $ time python2 -c exit
real 0m0.111s
user 0m0.016s
sys 0m0.078s
$ time python3 -c exit
real 0m0.063s
user 0m0.016s
sys 0m0.047s
Python 3 is consistently ~twice as fast. Both seem slower, but this is on a small laptop so the absolute measurements may not be comparable. This is on Creators Update.I've seen some large code bases take 4 seconds to import, > 80% being unused code.
In any case, given your points, it seems like a future Python version ought to introduce a new version of the import statement with lazy semantics (which, besides eliminating dead code, is also IMO the more correct/explicit behavior when importing symbols).
class LazyModule:
def __init__(self, name):
self.name = name
def __getattr__(self, key):
mod = {}
exec('import %s as mod', mod)
self.mod = mod['mod']
return getattr(self.mod, key)
class LazyImporter:
def get_module(self, name):
return LazyModule(name)I wonder if it would be possible to automatically rewrite a script to do that.
Clarity of dependencies is the “some reason”.
Like most style rules, there are times when breaking it is justified by other considerations, but it's not an arbitrary rule.
$ time python2 -c exit
cause Python to execute the following script: exit
This will look up the exit function, and then do nothing with it before the script exits due to reaching the end of the file. Interestingly, the representation of this function is set to generate the message that reminds you how to get out of the interactive interpreter if you type "exit".You can get the results you want with:
$ time python -c ''
meaning: Load Python, run a completely empty script, and clean up.Hope 3.7 finally puts it on par (or faster) than 2.7, but we've decided to migrate with 3.6 anyway. Don't take me wrong, I like having finally put 2.x behind, but it still bothers me a bit. Maybe we just have to get used to optimizing the "3.x series".
* this has been measured without startup time, just function calls, with horrible datetime.datetime.now() timings and %timeit magic-keyword from IPython -- always consistent.
You have wrong information.
It would be very hard for someone to say "python 3 is considerably slower". Startup is significantly slower, yes, but that's about it.
A tool gathering imports in one file if it is safe to do so would be really quite neat for deploying interactive Python applications (command line / GUIs).
On the more extreme end you'd have a C application linking not too many libraries (symbols are lazily loaded, libraries are not) that reaches main after 0.0001-0.0002 s (i.e. one to two hundred µs).
On the other extreme would be Java apps using heavy runtime-code-generating frameworks like Spring, where even a trivial app can take up to ten seconds to spring to life.
The video quite definitely states otherwise for most benchmarks. Only a few benches still show regressions over P2, and according to Victor they're unlikely to affect the vast majority of systems.
Like tensorflow - https://github.com/tensorflow/tensorflow/issues/1
I've just installed it using conda in Python 3.6 just fine.
So, just largest and more important part of Python's non-hobbyist users?
I don't really remember all that clearly, but my recollection is that numerous caveats were made fairly clear (like the new IO not being optimized and so on). I guess something needed to go out the door but I wonder if the biggest mistake was calling that release the 3.0 release (rather than something that would have better tempered naive expectations).
> - Bad support of the Python C API: PyPy was written from scratch and uses different memory structures for objects. The cpyext module emulates the Python C API but it’s slow.
> - New features are first developed in CPython. In january 2016, PyPy only supports Python 2.7 and 3.2, whereas CPython is at the version 3.5. It’s hard to have a single code base for Python 2.7 and 3.2, Python 3.3 reintroduced u'...' syntax for example.
> - Not all modules are compatible with PyPy: see PyPy Compatibility Wiki. For example, numpy is not compatible with PyPy, but there is a project under development: pypy/numy. PyGTK, PyQt, PySide and wxPython libraries are not compatible with PyPy; these libraries heavily depend on the Python C API. GUI applications (ex: gajim, meld) using these libraries don’t work on PyPy :-( Hopefully, a lot of popular modules are compatible with PyPy (ex: Django, Twisted).
> - PyPy is slower than CPython on some use cases. Django: “PyPy runs the templating engine faster than CPython, but so far DB access is slower for some drivers.”
So one could argue that pypy is just as much optimisation by "rewriting it in C".