6 ms·
The startup time fiasco was one of the reasons why Java never took over for GUI apps. Even though its unscientific, time to first usable interaction goes a long
by dman 9y ago
The startup time fiasco was one of the reasons why Java never took over for GUI apps. Even though its unscientific, time to first usable interaction goes a long way in establishing "speed" in the users mind. You should see the hoops that Chrome jumps through to excel on this metric.
- kstrauser 9y agoTrue, but: $ 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.
- philipov 9y ago> If you're spamming hundreds of processes from a looping shell script, You should absorb the loop into a single python process that instead calls the original script as a library...
- Too 9y agoMercurial has another approach. They have something called command server launched once and communicati g over socket if you need to invoke it thousands of times. If start up time is a problem with python your biggest problem is start up time with python, not the difference between 2 and 3.
- microcolonel 9y agoand I would point out that on my machine (GCC 6.3-based x86-64 Linux) the times are much closer ~ 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.
- kstrauser 9y agoThat's better yet - thanks for sharing! Most of my Python processes run for weeks at a go, so startup time isn't that important to me as long as it's not glacial. But 40ms (on my system) or 22ms (on yours) is totally acceptable for interactive shell usage. 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()?
- joshuamorton 9y agoIt absolutely is. Consider that that means that python takes 2-3 frames to start up. I'm not sure one should or could reasonably consider that "slow" for interactive use.
- microcolonel 9y agoMostly open, read, and fstat for python2: ~ 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.
- mkl 9y agoMy times on x86-64 Linux are similar to yours, but on the Windows Subsystem for Linux (which emulates the Linux kernel) it's a different story: $ 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.
- nomel 9y agoI think the problem is pep8. For some reason, pep8 says you load your modules at the top of the file rather than when needed. Giant libraries often follow pep8, meaning something like "import pandas" loads hundreds of python files, which gives the absurd startup times. I've seen some large code bases take 4 seconds to import, > 80% being unused code.
- smitherfield 9y agoBut couldn't that inefficiency be optimized away in the implementation? (Load imports lazily).
- marmaduke 9y agoIt can't be done automatically because imported can execute code. Since that's part of the semantics, you have to be lazy by hand.
- deckiedan 9y agoOnly on the first load ever. When modules are compiled to their byte code, they could get a "clean" flag if they don't execute code, which means they get loaded lazily next time.
- marmaduke 9y agoOk but figuring out what executes code might require executing code: consider non trivial use of meta classes, where an inconspicuous subclass actually invokes e.g. A registration process like a Django model class.
- smitherfield 9y agoSure, but, just spitballing here, could a substantial fraction of imported code benefit even with a very conservative heuristic? 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).
- intchanter 9y agoThis may not make much difference to these benchmarks, but these commands and the nearly-equivalent: $ 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.