[HN Gopher] Python 3.11 is faster than 3.8
___________________________________________________________________
Python 3.11 is faster than 3.8
Author : brrrrrm
Score : 309 points
Date : 2022-10-26 15:43 UTC (7 hours ago)
(HTM) web link (jott.live)
(TXT) w3m dump (jott.live)
| stuaxo wrote:
| Can you test some alternate pythons: pypy, pyston, pyston-lite ?
| riffic wrote:
| Waiting for Python 3.11 for Workgroups
| blitzar wrote:
| It is going to come on half a dozen or so double density disks.
| [deleted]
| Shish2k wrote:
| Checking for my own "benchmark", a gameboy emulator in several
| different languages[0]; it's CPU-bound but across ~3k lines of
| code, so _slightly_ more representative of real-world apps than a
| single-function tight-loop microbenchmark:
| zig: Emulated 600 frames in 0.24s (2521fps) rs:
| Emulated 600 frames in 0.37s (1626fps) cpp: Emulated
| 600 frames in 0.40s (1508fps) nim: Emulated 600 frames
| in 0.44s (1367fps) go: Emulated 600 frames in 1.75s
| (342fps) php: Emulated 600 frames in 23.74s (25fps)
| py: Emulated 600 frames in 26.16s (23fps) # PyPy py:
| Emulated 600 frames in 33.10s (18fps) # 3.11 py:
| Emulated 600 frames in 61.43s (9fps) # 3.10
|
| Doubling the speed is pretty nice :D Still the slowest out of all
| implementations though :P
|
| [0] https://github.com/shish/rosettaboy
|
| EDIT> updated the nim compiler flags to build in release mode
| like most other languages, thanks @plainOldText!
| stavros wrote:
| Can you try PyPy as well?
| Shish2k wrote:
| Apparently not :( (These benchmarks were done on an M1
| MacBook Pro) $ brew install pypy3
| pypy3: The x86_64 architecture is required for this software.
| verst wrote:
| $ brew install pyenv
|
| $ pyenv install pypy3.9-7.3.9
|
| I like using PyEnv for managing my Python versions. It will
| natively compile Python builds and should be doing the same
| on M1 (which is what I'm using). `pyenv install --list`
| shows you what is available.
|
| EDIT: Not sure why they don't have newer versions of PyPy
| there (I don't use PyPy) but all it takes is a PR to here:
| https://github.com/pyenv/pyenv
| [deleted]
| Shish2k wrote:
| Thanks! Added to the list, it's suspiciously only a
| little bit faster than CPython 3.11 though, which
| probably needs more investigation...
|
| ED> Looks like CPython prefers using a dict as a lookup
| table for opcodes (which is what this implementation
| does), while PyPy prefers having a long series of if-
| statements. Hmm.
| hnov wrote:
| That makes sense because pypy can JIT a ladder of if/else
| to a compare/jump conditional each whereas a dict lookup
| can be an order of magnitude more complex. If they're
| 8bit opcodes, maybe having a list based lookup table will
| perform similarly on py3000 and still optimize on pypy?
|
| Or maybe https://docs.python.org/3/library/array.html
| rather than list.
| pcwalton wrote:
| Looking at Rust vs. Zig, you have the FLAGS register in a
| bitfield for Zig but it's separate bools for Rust. This is
| probably making your Rust code slower because the CPU can't set
| multiple flags at once.
|
| I'm also wondering if all your #[inline(always)] is slowing
| things down.
| Shish2k wrote:
| Yeah, I really like zig's approach to bitfields, everything
| Just Works with no faffing about with bit-shifting and
| OR/AND'ing. I forget the exact reason I used separate bools
| for rust, but I remember spending a day trying to do
| something zig-like and failing...
|
| IIRC each of the #[inline] statements was tested and each
| made a noticable performance improvement. That's especially
| true for things like RAM::get() - since the gameboy does I/O
| by having different chunks of RAM act differently (some
| address ranges are just RAM, some are hardware controls, some
| read data from the cartridge, etc) you can replace the
| hundred-line generic get() with a single instruction if you
| happen to know that you are looking up one hard-coded
| address, and that address has no special behaviour.
| [deleted]
| insanitybit wrote:
| Very cool idea for a benchmark, thanks for the numbers. Pretty
| readable code as well, nice work. Is your benchmark running
| headless? I feel like that could be a source of noise but idk.
| Shish2k wrote:
| Yeah, all these benchmarks are measured in headless mode -
| all the calculations of what _should_ be on-screen are done,
| and pixels are written into a buffer ready to be displayed,
| but the Window is never opened and the buffer isn't blitted.
| mgkimsal wrote:
| Your comment in PHP src here
| https://github.com/shish/rosettaboy/blob/master/php/run.sh
|
| says
|
| # opcache in 8.1 gives a nice speedup (25s to 10s)
|
| Is the 23.7 seconds above using the 8.1 opcache?
| winter_blue wrote:
| It's amazing that Zig is faster than both Rust and C++. Kudos
| to the Zig team & Andrew Kelly!
|
| I wonder what optimizations Zig does that lets it generate
| machine code / LLVM bitcode faster than both C++ and Rust
| (which certainly have larger teams backing them), at least in
| the case of this Gameboy emulator project.
| cma wrote:
| Does zig have computed goto? That's important for emulators
| and virtual machines and C/C++ don't have it. Projects will
| often go out of their way to have a MinGW/gcc built module
| for core loops with that (gcc has it as an extension) even if
| the main project is built with MSVC.
| nerpderp82 wrote:
| If Rust wasn't able to elide bounds checks, that is most
| likely where the perf difference is from. Analyzing the
| output the assembly output from goldbolt or looking at the
| MIR can help.
|
| https://stefan-marr.de/2022/10/cost-of-safety-in-java/
|
| Unsafety buys you a little more performance, but the
| baseline should the safe version, not the unsafe version.
| It is like having to explain on a case by case basis why
| you aren't using lead pipes for this application.
|
| Always default to safety. The difference between safe and
| unsafe native code is usually single digit percentage
| points. Or weeks on a Moore scale.
| cma wrote:
| I think you replied to the wrong comment, mine was about
| zig vs C++.
| nerpderp82 wrote:
| I am talking about the whole stack of benchmarks and why
| there is a spread in perf. I am replying to you and the
| top level comment, if only the convos were a graph and
| not a tree.
| vjerancrnjak wrote:
| This should also be the case for nim. Generated C always
| looks very simple with -d:danger (when all memory access
| checks disappear).
| cb321 wrote:
| If I do nimble build -d:lto -d:danger
| --passC:-march=native I get 1920 fps while if I do nimble
| build -d:lto -d:release --passC:-march=native I still get
| 1775 fps. So, at least for Nim, the checks are only a
| 1.08x slowdown..Not so bad compared to the 2521 vs 1626 =
| 1.55x Zig-Rust slowdown on the author's machine.
|
| Heck, I see 1.33x differences in run times between the
| first & second run of the rust branch of his benchmark,
| but only 1.05x diffs in run times between 1st & 2nd Nim
| branch.
|
| In my experience, reasoning about things like this is
| rarely as simple as "bounds checks" which are (often) the
| most highly predictable branches.
| Shish2k wrote:
| Yeah, I'm really not sure how it managed that. I am
| _slightly_ suspicious, because while I was working on the zig
| version I spent more time running into compiler bugs[1] than
| writing my code, and so there's a _chance_ that it's running
| so fast by throwing away random chunks of important
| behaviour... but it still passes all of the test suite, so as
| far as I can tell this specific build is working correctly.
|
| [1] half the time I'd make the compiler crash; the other half
| it would generate a binary which crashes at runtime, with
| weird heisenbug behaviour like "adding a print statement to
| log how far down a function I am causes the code to stop
| crashing at all" -- like right now there is a load-bearing
| print statement which shows the address of the SDL Window
| object, because otherwise the compiler seems to optimise the
| Window out of existence and then a few lines later it
| segfaults on the null pointer...
| sirsinsalot wrote:
| > a load-bearing print statement
|
| Is the most glorious thing I ever heard.
| gw99 wrote:
| Interesting. On the trifecta of money vs pain vs speed, Go
| seems to be a reasonable compromise.
| Thaxll wrote:
| It's probably "slow" because of sdl and cgo not native Go
| code. A gb emulator doesn't do much actually, it's about
| fixed array, bit shifting, switch cases etc ...
|
| I ran a quick pprof and indeed it's spending a lot of time in
| cgo: Showing nodes accounting for 28720ms,
| 67.67% of 42440ms total Dropped 145 nodes (cum <=
| 212.20ms) Showing top 10 nodes out of 53 flat
| flat% sum% cum cum% 13080ms 30.82% 30.82%
| 16600ms 39.11% runtime.cgocall 4720ms 11.12% 41.94%
| 4750ms 11.19% main.(*RAM).get 2840ms 6.69% 48.63%
| 33070ms 77.92% main.(*GPU).tick 1970ms 4.64% 53.28%
| 3720ms 8.77% runtime.mallocgc 1450ms 3.42% 56.69%
| 1470ms 3.46% main.(*RAM).set 1160ms 2.73% 59.43%
| 41350ms 97.43% main.(*GameBoy).tick 1000ms 2.36%
| 61.78% 3160ms 7.45% runtime.exitsyscall 890ms
| 2.10% 63.88% 1610ms 3.79% main.(*CPU).tick_interrupts
| 820ms 1.93% 65.81% 850ms 2.00% runtime.casgstatus
| 790ms 1.86% 67.67% 5530ms 13.03% main.(*CPU).tick
| jbverschoor wrote:
| Yup.. a 240x performance difference (zig-py) has very
| little to do with the language, vm, or whatever. As soon as
| I saw that, I dismissed the benchmark.
|
| By these standards a 10 year old cpu with a beefy GPU will
| beat any new cpu as well.
| redox99 wrote:
| It depends really. In this case, a game emulator, you can
| only get away with it because it's for an ancient game
| console. But otherwise you definitely cannot afford 5x
| slowdown compared to CPP for a game.
| DeathArrow wrote:
| Also C# is quite reasonable.
| friedman23 wrote:
| Maximize pain for mediocre speed and money?
| Shish2k wrote:
| FWIW I personally found Rust the least-painful language, but
| that may well be confirming my pre-established biases :)
|
| - With Zig I kept running into compiler bugs, plus no package
| manager (I've vendored SDL and Clap into the source tree)
|
| - C++ I'd occasionally shoot myself in the foot in ways that
| other languages would have caught, plus no package manager
| (OS-level package management does an OK job, so long as you
| don't mind using old versions, and faffing about with
| different operating systems acting very differently)
|
| - The pain from Rust was one time where the compiler wanted
| me to specify a lifetime, and I didn't understand, so I just
| spammed lifetime specifiers in various places until it
| compiled. I've been using Rust for a couple of years now and
| I still don't really understand lifetimes, but thankfully 99%
| of the time I can avoid them.
|
| - Nim was a relatively nice language but massively lacking in
| available libraries (like even parsing command line arguments
| took me a day just trying to find a library which worked)
|
| - Go is pretty nice, my main pain is the tolerable but
| constantly-annoying verboseness of error handling (`err :=
| foo(); if err != nil {return err}` compared to rust's
| `foo()?`)
|
| - PHP I just hate on a deep and personal level thanks to
| years of being a PHP4/5 developer. The language is actually
| mostly-ok-ish these days, but the standard library is still
| full of frustration like inconsistent parameter orders within
| a family of functions.
|
| - Python is all-round really nice to write, but the test
| suite takes like 20 minutes to run, which really messes with
| my flow-state
| Thaxll wrote:
| "Rust the least-painful language"
|
| " I've been using Rust for a couple of years now and I
| still don't really understand lifetimes"
|
| Seems like a major pain point.
| pkolaczk wrote:
| As long as you don't get too crazy with references in
| structures or async code, lifetimes are not going to
| chase you.
| galangalalgol wrote:
| Generics too right?
| Ar-Curunir wrote:
| The reason it's not a pain would be explained by the rest
| of the sentence which you omitted: "but thankfully 99% of
| the time I can avoid them"
| Shish2k wrote:
| It would be if I ran into it regularly -- but after using
| the language for a variety of professional and personal
| projects for a couple of years, this is the only time
| I've actually needed to manually-specify lifetimes since
| the compiler normally figures it out for me :)
| robocat wrote:
| They are saying rust is painful. Just that they find the
| other languages even more painful.
| davisoneee wrote:
| Except that they don't really say rust was
| painful....just that there was one specific moment /
| aspect that they found tricky.
| pjmlp wrote:
| C++ has two relatively good package managers, conan and
| vcpkg.
| cb321 wrote:
| Re CLIs in Nim..Most find https://github.com/c-blake/cligen
| easy to use.
| UnpossibleJim wrote:
| This is actually a really nice write up for people deciding
| which language to learn/use if they aren't constrained.
| jetbalsa wrote:
| I find it /really/ funny that PHP is faster then python at
| this. as a PHP code hacker, I love that PHP keeps coming up
| faster then python in a ton of tasks
| throwaway894345 wrote:
| That's not much of a flex, Python is deliberately slow--the
| reasoning was that the implementation should be simple and
| they'd just expose the entire interpreter as the extension
| API, and then people would just write extensions in C when
| they needed the speed. Since vanilla Python is so slow, the
| entire ecosystem is highly dependent on C extensions for
| passable performance, and since the C extension API is
| virtually the whole interpreter, changes that would make the
| interpreter fast would typically break much of the ecosystem.
|
| Unfortunately, "just write the performance-sensitive bits in
| C" is pretty impractical because it only works when you're
| handing the C routine a relatively small amount of data
| relative to the amount of work to be done on that data
| (otherwise the costs of marshaling to C data structures will
| quickly eat up any gains from processing in C). And
| unfortunately, it turns out that a whole bunch of code works
| this way, so the whole bargain of "slow interpreter + easy C
| extensions" breaks down for a lot of real-world applications,
| but now we're locked into it.
| wheelerof4te wrote:
| CPython can be fast once you eliminate the main bottleneck:
| the interpreter itself.
|
| Processing loops adds a lot of overhead because the
| interpreter has to make the case jumps after each loop.
| Figuring out a way to minimize that overhead by using
| built-in data structures and stdlib library will speed up
| your code by an order of magnitude.
|
| Don't forget, the built-in types are already running in C.
| throwaway894345 wrote:
| I mean, yes, but that's probably not viable in many real-
| world applications. Usually you have a pretty complex
| data model (some graph-like structure) with Python
| methods that traverse it. You can't easily push that into
| native Python structures (at least not with any
| significant performance gain), and while you can push the
| whole thing into Rust or some faster language, at that
| point all of the interesting stuff is happening in Rust
| so why use Python at all (why pay the significant costs
| of a hybrid application)?
| pbowyer wrote:
| At least writing Python extensions is relatively easy (I
| understand, not done it) unlike PHP. PHP leans heavily on
| poorly documented C macros and the internals is tricky to
| grasp. At least it now has a minimal FFI module.
| throwaway894345 wrote:
| Honestly I think it's much better to optimize for the
| native use case rather than FFI.
|
| FFI can pervade an ecosystem making changes (including
| performance optimizations) to the host language more
| difficult. It also tends to complicate build and
| deployment stories. For example, from my Mac I can
| trivially build a native binary that will Just Work on
| any Linux system, even one without a libc. Contrast that
| with Python where I can't even install popular packages
| onto most non-Ubuntu Linux distros. And there's a lot of
| other things like that which crop up with pervasive FFI.
|
| I'm convinced that the FFI sweet spot is "difficult but
| possible" and native performance should be good enough
| 99% of the time.
| wk_end wrote:
| I'd be super curious to run a profiler on those Python builds
| and see where it's spending most of its time.
| talideon wrote:
| I think a bigger thing to point out is that it's within
| shouting distance of PyPy, and there's plenty more work that
| can be done to make it faster. Next up is a mini-JIT, which
| should help in places with tight loops.
| FerociousTimes wrote:
| Can you do Node 19.0 and Ruby 3.1.x too please?
| Shish2k wrote:
| TypeScript and Java are the two remaining languages where I
| feel I know them well enough to translate 3k lines of code in
| a weekend each -- I have approximately zero knowledge of Ruby
| though, and no motivation to learn it ^^; Pull requests are
| welcome though!
| FerociousTimes wrote:
| OK, I'll watch your repo and track the updates and see when
| you release the JS/TS port and then I'll a give it a try
| and port it to Ruby and send it your way.
|
| Best wishes
| plainOldText wrote:
| Just a quick glance at you repo, and I'm noticing you're
| running Zig `zig build -fstage1 -Drelease-fast=true` and Rust
| `cargo run --release` with the release flags on. You should do
| the same for Nim `nimble build -d:release --opt:speed`; Go too.
| Shish2k wrote:
| Updating nim's compiler flags, seems to be ~4x faster now :D
| nim: Emulated 600 frames in 0.44s (1367fps)
|
| Do you happen to know the right flags for release-mode Go?
| Last time I checked (admittedly years ago) I thought they
| just had the one "reasonably fast and reasonably debuggable"
| build mode
| Thaxll wrote:
| There is no release flag for Go.
| throwaway894345 wrote:
| To elaborate, Go is always in release mode because
| release compiles are about as fast as other languages'
| debug modes.
| LukeShu wrote:
| I'd phrase that as "release mode by default", not "always
| in release mode".
|
| There are various debug things you can turn on, such as
| the race detector, the memory sanitizer, or coverage
| tracking.
| plainOldText wrote:
| I do not, sorry. I'm sure some Go developer can chime in.
| cb321 wrote:
| With Nim `nimble build -d:danger -d:lto
| --passC:-march=native` I just got 1920 frames/s while with
| your rust build only 1237 fps on the same machine (EDIT:
| and 1307 frames/s with C++.)
| plainOldText wrote:
| In that case, did you also run rust with the equivalent
| RUSTFLAGS="-C target-cpu=native"? :)
|
| Perhaps benchmarks should be compared on equal footing,
| say, with the default release flag or all optimizations
| turned on, otherwise they're improper.
| cb321 wrote:
| I tried. That actually made the rust slower for me
| (i7-6700k, gcc-12.2, rustc-1.64). 1180 frames/s. And
| without the -march=native the Nim was at 1620. And it
| also did not help the C++ branch (but helped Nim about
| 1.2x).
|
| But really the original author/poster should do some set
| on his box. I cannot even compile/run all his things. The
| point of my comment was just to give a reference for how
| far off impressions can be from build flags. PGO
| (available to Nim, c++, but maybe not to Rust yet?) is a
| whole other set of maybe nothing burgers or maybe big
| improvements.
|
| (But, btw, I could not agree more that all experiments in
| this entire general space should have various big, bold
| disclaimers. Over-concluding from these things is
| rampant.)
| plainOldText wrote:
| Yes, tweaking the compiler flags can alter the
| performance substantially. I'm glad to see Nim so fast
| though.
| cb321 wrote:
| And with the author's hot off the presses nim flags I get
| only 1464 fps. So, 1920/1464 = 1.31 for my nim compile
| flags vs. his new ones, only a little less than the
| 2521/1626 that was interesting people.
|
| For something super jumpy like a simulator, I would find
| it unsurprising for PGO to make up (or surpass) the
| difference to Zig in both Nim and C++. 20 years ago there
| was this ACOVEA [1] project to try to discover great sets
| of gcc flags that could often find 2X improvements in
| object code speed for me.
|
| The range from build flags/procedures is often much
| greater than the supposedly interesting cross-language
| variation. These things often more measure developer
| experience/persistence than something intrinsic (and
| build flags/procedures are only part of that
| experience/persistence).
|
| [1] https://github.com/Acovea/libacovea
| streblo wrote:
| Is there such a thing for go?
| LukeShu wrote:
| It's the default for Go; with Go you have to explicitly
| turn on the debug features that you want.
| humanistbot wrote:
| I am shocked that PHP of all things has faster speed than
| python.
| bityard wrote:
| It's not as surprising if you look at the primary use case of
| PHP. It takes a request, does a bunch of stuff, and returns
| the result to the web server. And it needs to do all of it
| before the user who clicked on the link gets bored and goes
| somewhere else. (Or the API client calling it times out...)
| coldtea wrote:
| How is that relevant? This is not about it being faster for
| "it's primary use case" (optimized for that, etc).
|
| It's generally faster than Python in doing the same things
| as Python does, unrelated to web too.
| mgkimsal wrote:
| 100% not shocked at all.
|
| I recall a couple of times over the past 15-20 years where a
| current python significantly outperformed a current php
| version, but my recollection is that php was usually a bit
| faster, or sometimes a lot faster.
|
| PHP 7 was released on dec 2015, and gained significant speed
| bumps and better memory usage, with the average php execution
| time being cut in half, or more, generally without any code
| change whatsoever. It was quite remarkable.
|
| The path from 7.x-8.1 so far has generally seen incremental
| speed bumps again - usually somewhere between 3-8%
| improvements per release. Obviously this is going to be
| dependent on use cases, but overall it's been a fairly steady
| set of speed improvements over the last 7 years.
| crote wrote:
| I am not.
|
| PHP is traditionally used solely for websites. Some of those
| have grown rather large, to the point that having engineers
| optimize the language is cheaper than buying more servers.
|
| Python, on the other hand, is first and foremost a scripting
| language. When performance _does_ matter, you often end up
| using a wrapper around a C library, like NumPy. This means
| there is relatively little money in optimizing the Python
| interpreter.
| DeathArrow wrote:
| There are websites and large scale software. Google uses
| Python for a lot of its products.
|
| It would seem sensible that since Facebook poured a lot of
| resources in optimizing PHP, Google would have done the
| same for Python.
|
| Also, Python is the first or second most popular language.
| mgkimsal wrote:
| > Python is the first or second most popular language.
|
| By what metrics? Redmond quarterly from June shows Python
| at #2, and PHP at #4.
|
| https://redmonk.com/sogrady/2022/10/20/language-
| rankings-6-2...
| dragonwriter wrote:
| > > Python is the first or second most popular language.
|
| > By what metrics?
|
| Hmm, why don't you answer your own question?
|
| > Redmond quarterly from June shows Python at #2,
|
| That clearly is one that puts it "first or second", yes.
| mgkimsal wrote:
| Yes, it was partially an answer, and it's not saying
| Python isn't high up.
|
| But still wanted to know by what metrics the GP was
| making _their_ claim.
| fuckstick wrote:
| > It would seem sensible that since Facebook poured a lot
| of resources in optimizing PHP
|
| Well they sort of half assed tried years ago - they
| employed GvR at one point. Then they gave up and they
| continue to lean heavily on C++, Java and there is thing
| they developed in the interim: Go.
|
| > Also, Python is the first or second most popular
| language
|
| Hogwash. For all the open source and other development
| that occurs and is "indexed" on internet discussion
| forums there is countless boring ass shit behind the
| scenes in sweatshops around the world and corporate back
| rooms. PHP, Java, and C# are still probably more popular
| to start.
| hnzix wrote:
| Corporate has a faceless horde of Java devs.
| dragonwriter wrote:
| > For all the open source and other development that
| occurs and is "indexed" on internet discussion forums
| there is countless boring ass shit behind the scenes in
| sweatshops around the world and corporate back rooms.
|
| Much of which is also in Python.
| skybrian wrote:
| It can't be explained by lack of effort. There have been
| several serious attempts to make Python run faster,
| including one by some Google engineers. Many of them fail,
| and the ones that succeeded to some extent aren't
| mainstream. It's hard.
|
| For Python, the C integration probably makes things harder.
| coldtea wrote:
| PHP has always been several times faster than Python. Even
| more so with the speed updates post 7.
| sottol wrote:
| I think they did a lot of similar work to what python 3.11
| did and more when releasing PHP7. I'm absolutely not in the
| loop but remember postings here on HN a few years ago.
|
| Meta/FB is also pretty invested in Hack (was once a php
| dialect, again, out of the loop), maybe they contributed a
| thing or two?
| tedivm wrote:
| php7 was such a huge leap they skipped php6 (although there
| were other reasons for that).
| captn3m0 wrote:
| > Version 6 is generally associated with failure in the
| world of dynamic languages. PHP 6 was a failure; Perl 6
| was a failure. It's actually associated with failure also
| outside the dynamic language world - MySQL 6 also existed
| but never released.
|
| TIL MySQL 6
|
| https://wiki.php.net/rfc/php6
| KwanEsq wrote:
| Meanwhile Java(ECMA)Script bucking the trend by getting
| its failure out of the way at 4.
| hashar wrote:
| PHP 5 was kind of slow, to a point it threatened the future
| of Facebook (now Meta). They eventually went to transform
| it to CPP for speed improvement hiphop-cpp then went to
| build a VM with jit compilation. You could then deploy your
| app by transfering a sqlite file containing the compiled
| byte code.
|
| At Wikimedia we adopted it which has cut our CPU usage by
| half and has saved a few hundred of servers. We had some
| Facebook engineers helping which involved patching the
| Linux kernel while at it. Those were good times.
|
| Eventually PHP 7 followed up with a similar approach and
| had more or less the same performance as HHVM. Facebook
| went then to focus on the Hack language (a dialect of PHP
| with strong typing) and eventually phased out back compat
| with Zend.
|
| From what I remember, Sara Golemon at Facebook has done a
| lot of outreaching to Open Source project and gave us a lot
| of assistance (as well as others at Facebook).
| booi wrote:
| PHP has always been very fast of the untyped scripting
| languages even from the web 1.0 days.
| kstrauser wrote:
| That doesn't relate to Python, though.
| nerpderp82 wrote:
| Clearly we need a Python to PHP transpiler (trigger word) so
| we can be webscale (trigger word).
| captn3m0 wrote:
| PHP typically beats Python on CPU bound benchmarks:
| https://benchmarksgame-
| team.pages.debian.net/benchmarksgame/...
|
| (Measures Python 3.10.4 against PHP 8.1.5 - so expecting
| these to change a bit).
| treeman79 wrote:
| Back around 2003 I was hosting an internal web app for a
| fortune 50 company in python. It could handle 2 users at a
| time. I rewrote it in PHP. Scaled to hundreds with trivial
| work. Probably could have handled far more.
| toast0 wrote:
| PHP itself is pretty fast. It's the things that people do in
| PHP that get slow. Most of the Yahoo frontends were rebuilt
| in PHP in 200x because it was fast _enough_ and much more
| usable than the thing they used before(trigger warning: hf2k)
|
| Of course, people then go and build up sculptures of objects
| that will be thrown away after every request, and that stuff
| makes everything slow (that style of code is why PHP wasn't
| good enough for Facebook, IMHO), but you can build trash
| sculpture in any language.
| talideon wrote:
| PHP 5 and onwards have had a lot of resources put int o
| making it fast. The surprise for me is how close Python is
| getting to closing that gap.
| throwaway894345 wrote:
| Facebook dumped a ton of effort into making PHP fast over the
| last couple of decades. No one has been able to make Python
| especially fast without breaking compatibility with important
| libraries (Python exposed virtually the entire interpreter as
| its extension surface, and since Python is so slow,
| extensions are a major part of the ecosystem as they're the
| main way to recoup performance, which in turn means that
| changing the extension interface to make things faster would
| break a bunch of the ecosystem, and the Python maintainers
| are pretty scarred after the 2->3 breaking changes). Pypy
| comes close, and it has been grinding away to get
| compatibility, but last I checked you still couldn't so much
| as talk to a Postgres database through a reputable package.
| depr wrote:
| The last couple of decades? Facebook is not even two
| decades old. And they turned it into their own language.
| throwaway894345 wrote:
| Yeah, it was a crude estimate. Call it 10-15 years if you
| want.
| llimllib wrote:
| I wanted to see what the results for pypy would be.
|
| On my machine (very similar, a macbook pro m1 max):
| python 3.10: 52s python 3.11: 35s pypy 3.9.12:
| 10s
|
| (This test is basically a perfect test for JITs: one loop
| repeated many times)
|
| https://gist.github.com/llimllib/7af8144a92d3c2e1fc58be62988...
| masklinn wrote:
| > On my machine (very similar, a macbook pro m1 max):
|
| Should make essentially no difference then, since I rather
| doubt the Python implementation of n-body can leverage the GPU,
| or strains the RAM so much that the 200GB/s of the Pro (IIRC)
| would be an issue.
| bee_rider wrote:
| It looks very close for 3.11. The measurement from the parent
| comment includes two other python implementations (not
| covered in the article).
| [deleted]
| CalebJohn wrote:
| Out of curiosity I ran the same test on a linux laptop with the
| Ryzen 7 PRO 6850U CPU. python 3.10: 60s
| python 3.11: 46s pypy 3.9.12: 6s
|
| Looks like pypy performs comparatively better on x86_64
| [deleted]
| llimllib wrote:
| makes sense I guess, it's had a lot more development time I'm
| sure. Thanks!
| [deleted]
| metadat wrote:
| Why is there such a dramatic performance gap / slowdown for
| 3.10 + 3.11 compared to 3.9.12?
| arc-in-space wrote:
| That's 3.9.12 of _PyPy_ , not CPython
| qbasic_forever wrote:
| That's pypy 3.9.12, it has a JIT implementation to interpret
| python. The other two are standard CPython which doesn't JIT
| interpret the code.
| metadat wrote:
| Oops, thanks for clarifying.
| charlieyu1 wrote:
| Does pypy support numpy now?
| llimllib wrote:
| yes $ pip install numpy <snip
| building wheel> $ python --version && python -c
| "import numpy; print(numpy.identity(5))" Python
| 3.9.12 (05fbe3aa5b0845e6c37239768aa455451aa5faba, Mar 29
| 2022, 09:54:47) [PyPy 7.3.9 with GCC Apple LLVM
| 13.0.0 (clang-1300.0.29.30)] [[1. 0. 0. 0. 0.]
| [0. 1. 0. 0. 0.] [0. 0. 1. 0. 0.] [0.
| 0. 0. 1. 0.] [0. 0. 0. 0. 1.]]
| fordsmith wrote:
| Not OP, but are you taking into consideration that it is not
| Python 3.9, but pypy, which is distinct
| phendrenad2 wrote:
| How much faster? Should I update immediately or at my own
| convenience? Is this a game-changing speedup for my business?
| sdmike1 wrote:
| I'm seeing about a 50% speedup. It depends what you mean by
| game changing, but you should certainly see if 3.11 is a drop
| in replacement for whatever you are doing.
| DeathArrow wrote:
| I wonder what the performance would be if the code would have
| been compiled with GraalVM.
| Timja wrote:
| Javascript being 41x faster than Python seems a bit excessive.
|
| In my experience, having done quite a lot of dynamic language
| benchmarks, Javascript is about as fast as PHP and both are about
| 6x faster than Python.
|
| Has someone looked at the Python code used here, if it has any
| obvious gotchas?
| Spivak wrote:
| It's a benchmark that is basically the ideal case for a JIT so
| it's really Python vs. JS that got native compiled.
|
| I'm in no way criticizing the benchmark but that's the reason
| for the starker difference.
| brrrrrm wrote:
| let me know if you find anything! Happy to edit the post with a
| correction.
|
| For a little more information, this is using Bun 0.2.1, which
| uses JavaScriptCore (JSC), a part of WebKit which powers
| Safari. Since I'm running on an M1 Pro (Apple's ARM chip),
| there is probably somewhat of a benefit in using JSC.
| IshKebab wrote:
| It's not excessive in my experience. Javascript is usually very
| fast. Much faster than PHP and Phython.
|
| There are many flaws in this benchmark but the order of
| magnitude looks right to me: https://benchmarksgame-
| team.pages.debian.net/benchmarksgame/...
| pedrovhb wrote:
| There is one. The author's implementation of `combinations`
| runs in quadratic time making copies of lists on each
| iteration. I replaced that for `itertools.combinations`, which
| uses an iterator, and found a pretty big difference:
| ~/p/not_that_slow python3.11 modified.py 5000000
| -0.169075164 0.183753791 Time: 6.335 s
| ~/p/not_that_slow python3.11 main.py 5000000
| -0.169075164 -0.169083134 Time: 48.515 s
|
| Other than this, the only modification I made is to include a
| `print` statement at the end to show the time taken.
|
| EDIT: That is not actually equivalent, my bad. The iterator is
| consumed and the execution ends early, I didn't realize the
| algorith iterated over it multiple times.
| JJMcJ wrote:
| Heavy list creation is one way to really slow down Python.
|
| And itertools is a real gem, full of lots of goodies to
| handle list manipulation tasks.
| brrrrrm wrote:
| how're you using it? what you printed out (modified.py) seems
| to be a different result than expected
| xmddmx wrote:
| Semantic Versioning with numbers > 9 really breaks my brain
| sometimes - I read the headline as "Python 3.1.1 is faster than
| 3.8" - a performance regression - and thought "Oh no!"
| inasio wrote:
| Nice speedup! I'd love to see a comparison between 3.8 and 3.11
| of the same script, but using numpy
| ska wrote:
| wouldn't you expect numpy to mostly mitigate the differences?
| stabbles wrote:
| Even a 2x faster Python still makes a terribly slow language.
|
| Improvements look amazing relative to old Python. But compare it
| to PHP, Javascript, Lua. Ok, it might be better than Ruby
| sometimes.
| weatherlight wrote:
| I thought ruby is now faster than python. ( I know that wasn't
| always the case though)
| jensenbox wrote:
| I would love to see the OP benchmarks with Taichi applied:
| https://github.com/taichi-dev/taichi
| jhrmnn wrote:
| The boundaries are getting fuzzier. Implement this in Python
| _with JAX_ with little if any extra effort, run it on GPU, and
| you get performance you'd alternatively get only by writing
| custom CUDA kernels in C++.
| N1H1L wrote:
| Even cupy too. I have been using cupy for some of our own work,
| and it's so easy to do GPU based scientific computing, that
| it's funny now
| 3a2d29 wrote:
| I don't think the borders are that fuzzy.
|
| Who has a C++ repo that isn't in a low level language because
| it has to be?
|
| There is no production repo where python gets fast enough to
| replace Rust/C++.
|
| Still great to see improvements because there are repos where
| python replaces other languages.
| ReflectedImage wrote:
| Yeah but Python with Rust modules might be quite effective.
| behnamoh wrote:
| > JS is 41x faster than Python
|
| Except that Pythonistas often delegate such computations to
| libraries like numpy that achieve C-level speed. Python is
| supposed to be a glue language, JS is supposed to be a language
| that can run on browsers, so of course the two have different
| goals and performances.
| xyzzy4747 wrote:
| TypeScript is better as a glue language than Python IMO.
| brrrrrm wrote:
| I don't think there's much holding JS back from also being a
| glue language. JavaScript has certainly evolved from being only
| a browser language these days.
|
| The only request I'd have is more granular garbage collection
| (marking FFI memory as refcounted for more immediate
| destruction).
| UncleOxidant wrote:
| What about Python 3.10?
| nigerianbrince wrote:
| What they don't tell you is that python 3.8 was slower than 3.3.
| simonw wrote:
| I'm really impressed with the performance improvements in Python
| 3.11.
|
| I ran a very basic benchmark against a local web application: I
| got 413.56 requests/second on 3.10 and the exact same code gave
| me 533.89 requests/second on 3.11.
|
| That's a big enough increase that I think it's worth actively
| upgrading projects. Usually I wait for a few months for things to
| settle in first.
| oakwhiz wrote:
| Testing this out on a simple project. As a straw poll
| measurement, I was seeing 4.5 to 6 seconds on version 3.9 and
| 4.29 to 4.4 seconds on version 3.11. Definitely a noticeable
| improvement, for what it's worth.
| outworlder wrote:
| > Python is a popular but reputably slow interpreted language.
|
| _sigh_
|
| Why do people still say that?
|
| 1. There are no interpreted "languages", only interpreters for
| said language. One can compile or interpret anything.
|
| 2. When Java didn't have a Jit, it was still called "compiled
| language", even though it was running bytecode, same as Python.
|
| I think this "interpreted" vs "compiled" distinction is an
| anachronism. Pure interpreters are almost extinct.
|
| > (Javascript) It's a JIT compiled language with far more
| investment
|
| Oh, so it's compiled now?
|
| It's indeed due to investment, it wasn't always the case.
|
| > C++ is a compiled language
|
| Or is it?
|
| https://root.cern/cling/
| devmor wrote:
| Does anyone actually choose Python with speed as a defining
| factor? It's one of the slowest popular languages.
| brrrrrm wrote:
| most of the machine learning industry uses it almost
| exclusively as the driving language for GPUs
| verelo wrote:
| Python is in its awkward stage, something like PHP in ~2008. It's
| not super fast, it's got a good following but the changes to the
| core api's cause breaking changes, it's being used for things
| that maybe it shouldn't be, and it's facing a lot of competition
| from other languages.
|
| I had to laugh a few months back when someone suggested we switch
| a newish project to python from PHP 8.1 because "python is built
| in C" and "it's better for multithreaded math functions". A lot
| of misinformation out there.
| gcbirzan wrote:
| That anecdote says more about the people you work with than
| about Python.
| __mharrison__ wrote:
| Wow bun is fast! Would be interesting to see how NumPy or CuPy
| compare.
| bhaney wrote:
| > Wow bun is fast!
|
| Relative to python? I ran the benchmark in the post with both
| node.js and bun, and running it with bun consistently took ~60%
| more time. That was with bun v0.1.10 though. I tried with bun
| v0.2.1 but it just crashed.
| moderation wrote:
| Node (19.0.0) is quicker than bun (0.2.2) which is quicker
| than Deno (1.26.2) in my tests. (Edit: added Deno)
| mitata 'node sim.ts 10000000' 'bun sim.ts 10000000' 'deno run
| --allow-read sim_deno.ts 10000000' cpu: 11th Gen
| Intel(R) Core(TM) i7-1185G7 @ 3.00GHz runtime: shell
| (x86_64-unknown-linux-gnu) benchmark
| time (avg) (min ... max) ------------------
| -------------------------------------------------------------
| --- node sim.ts 10000000 803.35
| ms/iter (773.08 ms ... 848.1 ms) bun sim.ts 10000000
| 1.23 s/iter (1.19 s ... 1.4 s) deno run --allow-
| read sim_deno.ts 10000000 1.37 s/iter (1.27 s ...
| 1.69 s) summary node sim.ts 10000000
| 1.53x faster than bun sim.ts 10000000 1.71x faster
| than deno run --allow-read sim_deno.ts 10000000
| MR4D wrote:
| The actual title should be "Python 3.11 is _much_ faster than
| 3.8" to match the page.
|
| That missing word is important.
| Retr0id wrote:
| Indeed - I clicked expecting there to be some kind of catch.
| FpUser wrote:
| >"C++ is a compiled language, which means that it lacks some of
| the convenience of Python and JavaScript. Besides strict typing
| and having a generally ugly syntax, C++ also requires ahead of
| time compilation."
|
| To me ahead of time compilation is a convenience that in many
| cases catches bugs before they present all their glory to a
| customer.
|
| As for "generally ugly syntax" - beauty is in the eyes of the
| beholder. I am for example multilingual and do not get hung up on
| syntax unless it resembles brainfuck. However having fn instead
| of function, not having brackets when supplying parameter list,
| having variables to use some special characters does not qualify
| for "beauty". It is just a different way of doing the same thing
| and often feels that it is done for the whole purpose of being
| different or half arsed attempt to make parsing simpler.
| andybak wrote:
| > As for "generally ugly syntax" - beauty is in the eyes of the
| beholder.
|
| It's not entirely subjective. For example a language that is
| inconsistent in it's use of syntax could fairly be described as
| "objectively ugly".
| FpUser wrote:
| You just uglified nearly every language.
| andybak wrote:
| Ok. Maybe I should have qualified the example a little
| more.
|
| My point is - I don't buy that "language aesthetics are
| entirely subjective".
| girafffe_i wrote:
| mitchellpkt wrote:
| Anecdotally: wow just by upgrading from python 3.8 to 3.11 I
| measured a speedup from ~90 sec to ~60 sec runtime (in simulation
| code that mostly manipulates python built-in numbers and
| container datatypes)
| ehutch79 wrote:
| I see a lot of comments about how other languages are faster.
|
| Please think about your actual workload and take them with a
| grain of salt.
|
| For instance, for most web apps, you spend a large amount of time
| waiting on database responses. It looks nothing like the modeling
| the tests in the article do. Benchmarks are not typical
| workloads.
|
| Don't just assume because some random person on hn says zig is
| faster you should rewrite your business apps.
| PathOfEclipse wrote:
| I've actually found this to be completely untrue in practice.
| Just about every web service I've dealt with in production, if
| not all of them, have been CPU bound. This is for a number of
| reasons:
|
| 1) Network speeds have increased dramatically compared to CPU
| speeds.
|
| 2) People don't optimize code very much.
|
| 3) Web apps tend to do more work per request than they did in
| the 90s.
|
| Regardless, I've never seen an app saturate it's network pipe,
| but I've seen plenty saturate all their CPU cores, including
| relatively well-tuned ones. For instance, I wrote a Netty-based
| reverse proxy app once, and while I got it to run far faster
| than the typical app in that company, it was still CPU-bound in
| all my tests.
| hannofcart wrote:
| +1 to this.
|
| We picked Python Asyncio based Tornado async for our
| services. As soon as we hit scale we were getting CPU bound.
|
| Deep diving into profiling came up with JSON parsing being
| the culprit.
|
| It's a painful problem to crack once you hit those limits. In
| some cases you could genuinely skip parsing the JSON (by
| returning a raw JSON containing string to client) such as
| when you are simply getting data from cache or db.
|
| In other cases you simply can't skip it. For eg when you are
| interfacing with a 3rd party library that will only speak
| JSON. At that stage you are stuck.
|
| You could try and use a wrapper around faster native JSON
| parser (say uJson) but it will be a trade-off between the
| parsing time and the time taken to copy the string to the FFI
| parser and copy back the results. And deal with all the
| complexity that that entails.
|
| Or you could hand it off as a job to an async queue (this
| might be the canonical architectural approach to prevent
| blocking the event loop) but then you have just shifted the
| problem to a different place where you'll still need to throw
| more instances at the problem. And this adds extra latency.
|
| I too was in the "don't optimize prematurely" camp but
| picking Python today for new services IMO would be taking
| that principle a bit too far.
|
| Especially considering the ergonomics that modern languages
| like Golang or Rust offer.
| dragonwriter wrote:
| > It's a painful problem to crack once you hit those
| limits.
|
| If you hit that doing something novel and obscure, sure. If
| it is literally parsing JSON, you spend a little effort
| researching non-stdlib JSON parsing libraries, pick one of
| the several stable much-faster-than-stdlib ones, and move
| on.
| hannofcart wrote:
| Like I mentioned we did that. You can get a small
| arithmetic multiple speed up. But moving these services
| to rust basically made our instance counts drop from 32
| to 2.
|
| Once the team has the know-how to write a service in
| Rust/Golang or even the modern pleasant to write Java, it
| becomes hard to justify why we'd pick Python for a new
| service at all.
| superbatfish wrote:
| He explicitly mentioned that path...
| dragonwriter wrote:
| He explicitly mentioned some of the troubles you might
| have implementing and maintaining that yourself via FFI.
|
| He very much did not explicitly mention that its already
| done, with established results, and that the described
| "pain" isn't something you have to take on at all.
| ehutch79 wrote:
| I'd argue a lot of web apps are just serializing to json,
| after doing minimal business logic that likely has to do db
| requests.
|
| Once again, I said to look at what your load actually is. If
| you're CPU bound, then yes, buy a bigger instance, optimize,
| or switch languages.
|
| It's like how if you are putting up a blog, you probably
| shouldn't be looking at running kubernetes clusters for just
| that blog.
| skrtskrt wrote:
| Yeah I've profiled slow Python apps before and it's almost
| always serialization that's the sticking point. Default
| implementation of date parsing in particular is really bad
| PathOfEclipse wrote:
| You might be surprised to find out how CPU-intensive even
| something as simple as a DB request can be. Your driver has
| to do the work of communicating with the DB server via its
| protocol, which is similar in cost to any other network
| request. More importantly, it has to deserialize the result
| and marshal the data into objects on the managed heap. Most
| DB drivers don't support streaming, so for larger requests
| you have to read all the data into memory, then convert it
| all into objects at once.
|
| And that's not even taking into account frameworks and ORMs
| like Hibernate, which itself can multiply the CPU used
| several-fold on top of JDBC, or whatever lower-level
| interface it wraps. I've never measured frameworks in
| dynamic languages, but I have no reason to believe they
| aren't similarly inefficient.
|
| And, yes, one of the optimizations I did for my reverse
| proxy app was to upgrade the JSON library, which brought a
| significant performance boost. But it's not the only source
| of CPU usage for apps, nor was it the only major
| optimization I successfully applied.
| williamcotton wrote:
| And then there is the resource usage... a typical dynamic
| interpreted language uses orders of magnitude more CPU and
| memory compared to compiling to machine code. Enough of these
| apps running in a data center can add up to a lot of wasted
| resources!
| IshKebab wrote:
| Yeah this is a constant excuse for Python's slowness but I have
| yet to work with a Python codebase that _wasn 't_ slow.
|
| I mean I could buy it if Python was maybe 5-10x slower than
| "fast" languages, but the benchmarks people are throwing around
| show it is 50-100x slower. Every Python codebase I have used
| (apart from one-off scripts I guess) has eventually run into
| the "ok it's slow, how can we make it faster?" barrier.
| ehutch79 wrote:
| So, python is slower than go, rust, zig, etc. OK we agree.
|
| Now does it matter? Not all codebases are the same. If I'm
| serving api requests, does it being 55ms vs 15ms make a
| difference? 110ms vs 75ms? If you're writing analysis on a
| huge data set and an iteration takes 100ms vs 50ms? yeah that
| could be the difference between weeks vs days.
|
| Almost like someone should look at what they're doing before
| saying 'IshKebab said python is slow, so we should rewrite
| all our code'
| aidos wrote:
| For most cases it just doesn't matter.
|
| I make software that requires searching over large datasets
| (image recognition for construction drawings). It's a web
| app running python on the server and it feels instantaneous
| for users as they're searching.
|
| Most people aren't even doing that - they're just pushing
| and pulling data from a db. Building maintainable software
| is what really matters.
| ReflectedImage wrote:
| Well those sort of time differences would make a
| difference.
|
| But usually 90% of the response time for the api request is
| the time it took the SQL server to execute the relevant
| queries.
| fazfq wrote:
| >If I'm serving api requests, does it being 55ms vs 15ms
| make a difference?
|
| Yes, it's the difference between being able to serve 66 r/s
| or 18 r/s.
| killingtime74 wrote:
| I've worked at places where both your comparisons
| absolutely matter. 55ms vs 15ms for a domain specific
| search engine breaks the budget of 20ms. 110 vs 75 broke
| the budget of a ML API. Not everyone has the luxury of not
| caring about speed
| DeathArrow wrote:
| >For instance, for most web apps, you spend a large amount of
| time waiting on database responses.
|
| Still, for web apps there are still huge gaps based on language
| and framework used. [0]
|
| [0] https://www.techempower.com/benchmarks/#section=data-r21
| mastax wrote:
| For a long time many of the .NET Runtime's most fundamental and
| performance-sensitive functions were written in C++. In the
| beginning the JIT wasn't fast enough, or C# didn't have good
| enough native interoperability, or it didn't have the tools to
| write fast code. As the years went on the JIT got faster, and
| more and more improvements were added to help write high
| performance C# code. Now there's a mass effort to port most of
| the runtime to C# to make it safer, more maintainable, and often
| faster. RyuJIT may not generate code as nice as LLVM but there's
| so much overhead calling into native code that there are gains to
| be had.
|
| Imagine the alternate timeline where numpy is removing some of
| its C function calls because Python is fast enough on its own.
| I'm not sure we can make it there from here.
| PaulHoule wrote:
| That n-Body simulation is a bad case for Python today in that you
| loop over the differential equation solver in Python. (It's like
| the very branchy semantic web and old AI stuff that I do for
| fun... I am migrating a lot of that to Java, PyPy helps a great
| deal but Java does a lot better.)
|
| If you are doing heavy matrix math, numpy runs at FORTRAN speed,
| tools like scikit-learn and Tensorflow also get high performance
| by doing the heavy lifting outside Python.
| systemvoltage wrote:
| It is still informative to see how slow native Python really
| is.
| bkanuka wrote:
| I agree. This was honestly news to me - who very often uses
| Python for maths. However, I would _never_ write the code as
| he did (instead I would rely on numpy /scipy). So I would
| also be intersted in a numpy version of the same test.
| ReflectedImage wrote:
| How exactly would you write a gameboy emulator in
| numpy/scipy?
|
| It's sequential code with fiddly side effects. I know I've
| written one.
|
| But I'm generally curious if this is in-fact possible in
| someway.
| adgjlsfhk1 wrote:
| Numpy would probably be even slower here. Numpy is good
| when you have large arrays, but it adds roughly .1 to 1 us
| per call in overhead.
| bkanuka wrote:
| Without validating anything myself, I was able to find
| this post https://hilpisch.com/Continuum_N_Body_Simulatio
| n_Numba_27072... which showed a simple n-body program
| sped up by ~670 times when moving from pure python to
| numpy+numba.
| adgjlsfhk1 wrote:
| 2 things to notice: the first is that this is with 5
| bodies while your link was with 1000. For 1000 bodies,
| numpy is a noticeable speedup (100x). For 5 particles (I
| used the same code as your article but adjusted the
| number of particles) numpy is 5x slower. Adding numba
| would make this fast again since it would remove the
| overhead, but at that point, just use a fast language in
| the first place.
| nerpderp82 wrote:
| You should give JAX a go.
|
| https://github.com/google/jax
| patrickkidger wrote:
| +1 for JAX. Basically designed to be the successor to
| TensorFlow, and much nicer to work with. Strangely I've not
| seen it discussed around HN much but it's what I do 100% of
| my work in these days.
|
| Whilst I'm here: shameless self-promotion for Equinox and
| Diffrax:
|
| https://github.com/patrick-kidger/equinox
| https://github.com/patrick-kidger/diffrax
|
| Which are neural network and differential equation libraries
| for JAX.
|
| [Obligatory I-am-a-googler-my-opinions-do-not-represent-your-
| employer...]
| IshKebab wrote:
| To paraphrase:
|
| > That benchmark shows that Python is slow. If you avoid
| writing your code in Python it can be really fast!
| andybak wrote:
| > numpy runs at FORTRAN speed
|
| Not everyone will be aware that this meant as praise. ;-)
| PaulHoule wrote:
| Yep.
|
| FORTRAN codes persist today because (1) the old school memory
| model of FORTRAN is fast, and (2) it is so easy to write
| numeric codes that do the wrong thing with rounding and
| numerical instability. There's a reason why Foreman Acton
| wrote a book titled _Numerical methods that (usually) work_.
|
| https://www.amazon.com/Numerical-Methods-that-Work-
| Spectrum/...
|
| Code something up in C, Haskell, oCAML or CUDA and you miss
| out on the 40+ years of experience people have had with a
| FORTRAN code from the 1970s.
| pbowyer wrote:
| > (2) it is so easy to write numeric codes that do the
| wrong thing with rounding and numerical instability.
|
| Are you saying FORTRAN avoids these problems, or that it is
| prone to them? If the former, how does it do it?
| PaulHoule wrote:
| Ideally, people who understood numerics wrote the code in
| the 1970s and it has gotten heavy use since then so if
| there are problems with numerical instability they've
| been detected and solved.
|
| Today somebody who doesn't know numerics frequently codes
| something up for the wrong reasons (e.g. to learn a new
| language, because they think the 1970s FORTRAN code is
| obsolete, ...) and never did the testing to know that the
| code they wrote is numerically stable or not.
|
| That is, you might think it is pretty easy to code
| something numerical up, and sometimes it is, but
| frequently you write something that's a little bit wrong
| and sometimes you write something that's terribly wrong,
| sometimes it isn't even wrong.
|
| It's not that FORTRAN is necessarily more accurate than
| another language, but that you can trust a code that has
| been around for 40 years and codes that have been around
| 40 years have been written in FORTRAN.
|
| ---
|
| As for the memory model I think about it the most when I
| write embedded programs for my Arduino.
|
| It drives me nuts that C diddles the stack pointer around
| meaninglessly when for most of the programs I write there
| are a small number of parameters that decide the size of
| all the arrays (like an old FORTRAN program) and local
| variables, recursion and all that are a source of
| problems and not solutions.
|
| The only reason I write C for that thing at all is that
| some of the programs I write are performance sensitive
| and I could get a bigger boost running the C code on an
| ARM or ESP32 than I could get writing AVR8 assembly and
| eliminating meaningless loads, stores and other activity
| that C does "just because".
| fragmede wrote:
| A lot of physics simulations use FORTRAN for the existing
| libraries, and there's a way to run it on GPUs. It's not
| going anywhere.
| TheRealPomax wrote:
| Sounds like a case of "write the code to show what it _should_
| look like and show what numbers you get compared to the code
| they posted "?
|
| But remember that the exercise wasn't "to run the n-body
| simulation", or even "to run maths", but just to see how fast
| "plain Python" is with the release of 3.11 - using numpy and
| scipy, which rely on compiled code that they can hand work off
| to, would make any runtime value you get completely meaningless
| for the purposes of benchmarking pure Python =)
| PaulHoule wrote:
| The viability of Python for scientific work is predicated on
| using Python as glue code for code written in other
| languages. If pandas ran at the speed of Python people really
| would be using Julia or some other language instead of
| Python.
| bornfreddy wrote:
| Who cares about "pure" Python? The whole point is that you
| have powerful libraries at your fingertips and you can
| leverage those to get _fast_ code. Can you do the same in Go?
| JavaScript? PHP?
|
| I'm tired of people comparing languages but then leaving out
| the major winning points for Python. Numpy & co. are integral
| part of Python, no serious ddv would use just "pure" Python
| for numerical methods, ever. So let's compare real'world
| Python, shall we? I doubt Go has a chance then. /rant
| bee_rider wrote:
| Clearly the solution is to add a jitter to Python that
| identifies code that looks like an matrix multiplication, and
| calls numpy instead.
| [deleted]
| zitterbewegung wrote:
| The point of making python faster is not just making the above
| nbody simulation faster but also to improve the performance of
| when python is used as glue code to other more efficient systems.
|
| But, the language before has a bigger shift to making it faster
| due to the amount of resources it has now that are dedicated to
| making CPython faster similar to what happened with JavaScript. I
| hope CPython eventually is as fast as JavaScript.
| verst wrote:
| Now just waiting for the GitHub Actions runners to be updated
| with Python 3.11 (deployment next week - they deploy image
| updates weekly).
|
| https://github.com/actions/runner-images/issues/6459
| ilovecaching wrote:
| At this point virtually everyone agrees that dynamic type is only
| good for scripting and cross-domain code, not for being robust
| software applications. Considerable effort has been spent over
| the years adding typing back to dynamically typed languages
| (Typescript, python has several).
|
| If you want to build real software, you should be looking at Go
| or Rust, not Python. They are already fast, they already have
| concurrency, and now with Go's generics it's safe to say that
| their type systems are exactly what are needed to build real
| software in 2022.
| [deleted]
| ReflectedImage wrote:
| You can build robust software applications with Python. It just
| needs different development practices. Using static typing with
| Python is a bit dumb imo.
|
| Basically you write a ton of 3k line scripts, have them talk to
| each other a message queue like RabbitMQ and have a SQL Server
| e.g. PostgreSQL server do all the heavy lifting for you.
|
| You can't do any program like that but 80% of programs that are
| written in businesses can be done like that. Typical CRUD
| stuff.
|
| And you can develop it at 3x times the speed then if it was
| done in a more traditional language like Java/C# etc..
|
| Python is a powerful language if you use it for the right use
| cases.
| visarga wrote:
| How do I run the latest diffusion model in Go or Rust?
| snicker7 wrote:
| I am not sure if the JS vs. C++ benchmark is really fair. Using
| unix "time" utility, you are also including the startup of the JS
| runtime.
| melling wrote:
| "Besides strict typing and having a generally ugly syntax, C++
| also requires ahead of time compilation."
|
| What's wrong with strict typing and ahead of time compilation as
| long as it compiles fast? Doesn't this prevent many runtime
| errors that can occur in Python?
|
| Python is a higher level language than C++ so it requires less
| effort but newer compiled/typed languages offer more of what
| Python is good at
| klodolph wrote:
| I have worked with very few C++ projects that compile fast, and
| my experience is that the errors in C++ projects are often more
| severe than the errors in Python projects. Even with modern C++
| smart pointer style, I've seen all sorts of stuff like dangling
| pointers / use-after-free, buffer overruns, etc. All in code
| that had been reviewed.
| tomovo wrote:
| Try any larger Swift project and suddenly C++ looks pretty
| fast. Agreed on the pointers though.
| melling wrote:
| Yes, C++ was created in the 1980's and a lot had been added
| ...
|
| That's why I was suggesting newer compiled languages
| incorporating some of what we've learned over the past 4
| decades. eg type inference
| PathOfEclipse wrote:
| In general, the more work the type system is doing for you,
| the slower the compilation speed. Kotlin and Scala, for
| instance, both compile far more slowly than Java. I think
| even C# compiles very slowly compared to Java. You mention
| type inference, but type inference actually slows down
| compilation, and the more sophisticated the type inference,
| the slower the compilation!
|
| Similarly, Rust compilation speed is much slower than
| GoLang's, whose type system does relatively very little for
| you. I haven't seen exact numbers, but I've seen people say
| Rust and C++ have similar compilation speeds, and both are,
| in general, slow to compile.
| cestith wrote:
| Rust gives you so much more for the same compilation
| speed though.
| galangalalgol wrote:
| In my experience a good pipeline with decent unit tests makes
| c++ and python work fine.
| ahartmetz wrote:
| And Valgrind (and / or Memory Sanitizer), they mostly
| remove a big source of problems in C++ code.
| agumonkey wrote:
| I see a strong convergence of typed / fast / expressive
| languages between python/php/ruby and cpp/ada. Rust is one
| trendy instance but I believe it's gonna create a spot around
| it.
| maccard wrote:
| > What's wrong with strict typing and ahead of time compilation
| as long as it compiles fast? Doesn't this prevent many runtime
| errors that can occur in Python?
|
| Nothing, as long as the compilation is fast. C++ compilation is
| not fast. The large C++ projects I've worked on over the last
| few years, compilation is bordering on 2 hours for a full
| build, and 10-60s for incremental builds. At one point,
| incremental changes were taking 15 minutes to link at one point
| (resolved by [0]). Go is a great example of fast compilation
| and strict typing IMO.
|
| [0] https://devblogs.microsoft.com/cppblog/improved-linker-
| funda...
| wtetzner wrote:
| > Go is a great example of fast compilation and strict typing
| IMO.
|
| I think an even better example might be OCaml. Ocaml's
| compilation speed (last time I checked) was on par with Go,
| but it provides a much nicer (IMO) type system.
| the_svd_doctor wrote:
| C++ (especially template heavy with lots of headers and so
| on) is certainly not fast to compile. But 2 hours that's
| crazy. What sort of codebase and on what kind of machine?
|
| A 128 cores threadripper is a great workstation to compile
| C++ code fast :D
| [deleted]
| MH15 wrote:
| Chromium is known for taking hours.
| nequo wrote:
| That is true. But Chromium is not in the realm in which
| the compiled vs. interpreted debate is relevant. It is
| slow to compile, but it would also be very slow to run if
| it was written in Python.
|
| (Unless a hypothetical Node.js rewrite would be
| comparable on speed. I wonder how it would do on memory.)
| redox99 wrote:
| More like an hour or less on reasonable, consumer
| hardware[1]. A lot less on workstation/server CPUs, or
| with IncrediBuild.
|
| [1] https://youtu.be/nRaJXZMOMPU?t=770
| anthk wrote:
| Most people will use ccache under Unixen.
| redox99 wrote:
| For reference Unreal Engine 5 full build (building a lot of
| stuff you don't need) takes like 30 minutes on a 3950x.
| Typical incremental build is either 15 seconds, or a minute
| if I touch some popular header. For full build not only you
| can have a lot more cores, you can use IncrediBuild.
| Beltalowda wrote:
| Go was designed, in part, as a response to C++'s slow compile
| speeds. The Go compiler has gotten a bit slower over the
| years, but it's still pretty fast, especially when compared
| to C++ or Rust.
|
| > In 2007, build engineers at Google instrumented the
| compilation of a major Google binary. The file contained
| about two thousand files that, if simply concatenated
| together, totaled 4.2 megabytes. By the time the #includes
| had been expanded, over 8 gigabytes were being delivered to
| the input of the compiler, a blow-up of 2000 bytes for every
| C++ source byte.
|
| https://go.dev/talks/2012/splash.article#TOC_5.
|
| I also hate how just adding some definition to a .h file
| that's only referenced in one .c (or .cpp) file will
| recompile loads just because the header file changed. Maybe
| there's ways to improve on that (ccache?), but I mostly write
| C to contribute to open source projects (rather than my own)
| and it can be an annoying wait.
| snovv_crash wrote:
| You can limit the impact of this with forward declarations
| and only putting that is needed for the public API into the
| header includes. The rest can all live in the .cpp
| exabrial wrote:
| > What's wrong with strict typing and ahead of time compilation
| as long as it compiles fast? Doesn't this prevent many runtime
| errors that can occur in Python?
|
| Nothing, it's all good things: It's easier to write, easier to
| debug, and the compiler (not the user) catches bugs.
| wiseowise wrote:
| C++ compilation is anything but fast.
| DeathArrow wrote:
| >Python is a higher level language than C++ so it requires less
| effort but newer compiled/typed languages offer more of what
| Python is good at
|
| I see Nim as clearly better if you write a larger software.
| It's a shame it's usage is low and thus there aren't many Nim
| resources.
| polotics wrote:
| I think Nim is best placed as the choice for the fast
| functional core performance-critical and cpu-bound few parts
| of a larger python codebase.
| mg wrote:
| Is the performance difference of Python and Javascript due to the
| language or due to the runtime?
|
| If one would compile both, the Python version and the Javascript
| version, to WebAssembly and execute that, how would the
| performance differ then?
| edflsafoiewq wrote:
| Python and JS are basically the same language in terms of
| semantics.
| dragonwriter wrote:
| > Python and JS are basically the same language in terms of
| semantics.
|
| Python is dynamic class-based OO with multiple inheritance.
| JS is dynamic prototypical OO, though it has recently added
| convenience syntax implementing single-inheritance class-
| based OO on top of it.
|
| They are not the same.
| Symmetry wrote:
| Python also has much stronger typing in to converting types
| of things willy nilly without being instructed to.
| edflsafoiewq wrote:
| It's still redirecting to another object at runtime in both
| cases. The details are obviously not exactly identical but
| there's no great difference in the object model just
| because one is called a "class" and one is called a
| "prototype".
| _ZeD_ wrote:
| well, as long as both of them are descendant of modula 2 :)
|
| but no. while both languages share some similarities
| (dynamically typed, some form of "objects" and "classes")
| there are a lot of differences, both at "language level" and
| at "implementation level"
| edflsafoiewq wrote:
| What are some important differences do you think?
| brrrrrm wrote:
| It's due to the runtime.
|
| JavaScript has a runtime that updates as it executes. It
| notices a loop is being run frequently and then compiles a new
| version of the loop that runs faster.
|
| Python doesn't have this functionality.
|
| WebAssembly is for running things in the browser and would slow
| everything down (Python, JS, C++). The tests in the post are
| run natively (on my command line).
| squeaky-clean wrote:
| Just some extra info to add to this for OP/others. The
| keyword to Google to learn more about this would be a "JIT
| compiler". If you were to run each of those benchmarks to
| loop only a few times (or steps for the n-body example), say
| n=10, they would appear much slower because the JIT compiler
| needs lines of code to be run multiple times before it can
| begin making optimizations.
|
| "pypy" is an alternative runtime for Python which can do JIT
| optimizations like Javascript interpreters do. Another
| commenter in a different subthread already posted a quick
| speed comparison involving pypy, it's much faster than the
| standard python runtime (called CPython).
|
| But pypy isn't necessarily a synonym for Python (which almost
| always means CPython). It doesn't have 100% compatibility
| with 3rd party libraries (it's probably 99.9% but just 1
| unsupported dependency is enough to prevent your whole
| project from going pypy).
|
| And also with most Python projects, the python code isn't the
| slow part of the stack. If you're making a web app, your
| cache and database is probably where 99% of your request time
| is spent. For scientific computing, data analysis, or ai
| training, you're usually using 3rd party libraries written in
| a "fast" language like C/Fortran/Rust with python hooks, and
| your python just acts as glue code to pass data between these
| library calls.
| [deleted]
| cogman10 wrote:
| Python does have this functionality, but it's hamstrung by
| the implementation.
|
| Javascript is, for the most part, completely sandboxed and
| separate. Which means the JIT for Javascript is totally free
| to do neat things like move an object from one region of
| memory to another.
|
| CPython, on the other hand, has to care about things like
| "was this object created in C? Is it pinned to that memory
| location? Does this method end up delegating to C?"
|
| And you see that in the complexity it takes to introduce
| native methods in both. Moving and using data from JS to
| Webassembly is a PITA. Accessing data in a Python object from
| c ( and vice versa) is trivial.
|
| That triviality is what gets in the way of JIT optimizations.
| brrrrrm wrote:
| I don't buy this argument. WebAssembly is a vastly
| different beast than trivial C extensions (since WASM is a
| browser thing). JavaScript has both and is still much
| faster.
|
| Bun (the runtime I used for the post), has a native C
| interface that's far simpler to use than Python (even with
| pybind/nanobind): https://github.com/oven-sh/bun#bunffi-
| foreign-functions-inte...
|
| Deno (a v8-based runtime) has the same thing:
| https://deno.land/manual@v1.25.4/runtime/ffi_api
|
| These use the standard C-ABI directly without requiring
| headers (unlike Python).
|
| Node.js standardized a more Python-like C API called Node-
| API: https://nodejs.org/api/n-api.html
|
| I believe Python can continue to add performance and is not
| hamstrung by the implementation.
| cogman10 wrote:
| The difference between all of these and how the python c
| api works is that 1 layer of abstraction and translation.
|
| Take the deno example, in order to invoke a C function
| you have to tell deno "load this lib, this dynamic
| function is here, and the method signature looks like
| this".
|
| Look at what types are permitted to be passed between the
| two as well. deno isn't exposing deno objects to C, it's
| exposing only simple primitive types. The cpython FFI, on
| the other hand grants C full access to python objects.
|
| That one layer of abstraction and distance makes all the
| difference and is hard to backport in.
|
| There's a reason alternative pythons (pypy, graalpy)
| don't really support it and struggle to support libs that
| rely heavily on it (like tensorflow).
| brrrrrm wrote:
| You can expose objects. Here's how it is done in Bun: htt
| ps://github.com/facebookresearch/shumai/blob/main/shumai/
| ...
|
| We've been using this feature heavily in Shumai.
|
| I think you are vastly overestimating the complexity
| associated with this (user exposed ref-counting/garbage
| collection) and may not be totally up to date on what's
| implemented.
| cogman10 wrote:
| > I think you are vastly overestimating the complexity
| associated with this
|
| No, I think you are misunderstanding the problem.
|
| I'm not saying that, with a good 3rd party lib,
| generating FFI APIs can't be easy and slick. I'm saying
| that non-python languages have more complicated FFI APIs
| that practically necessitate these sorts of generation
| libraries (like bun).
|
| When you grab a bit of memory out of an object in C with
| python, you are reaching directly into python's internal
| representation of the object and tickling the bits there.
|
| When you do that with deno/javascript/others, there's a
| layer of abstraction introduced to keep our native method
| from directly tickling the bits that the VM is aware of.
|
| That's the problem.
|
| From C, you can create a new python object, store it off
| in a global variable, send it back to the python vm, and
| later in a thread go tickle some of the bits and see that
| tickling in the Python VM. Because that object is the
| same one used by Python and C.
|
| The complication that arises with CPython is many very
| popular librarys (numpy, tensorflow, pandas) rely HEAVILY
| on the fact that the objects they are working with in C
| are the same ones python uses. That's why they've been so
| slow to port to pypy if at all.
|
| And that ability for C libraries to very deeply interact
| with the VM is exactly the problem that makes it hard to
| improve CPython's JIT. That's the reason other python
| JITs, like pypy, either don't or have very limited
| support for CPython's FFI capabilities.
|
| The reason FFI works so well with other languages is they
| drew very tight and clear boundaries around how
| interactions work and who owns what when.
|
| So please, stop spamming "bun". It's a non sequitur.
| brrrrrm wrote:
| I'll concede that Python has more nuanced bits of
| complexity exposed, but I suspect a willingness to break
| compatibility for the sake of performance would benefit
| the language a lot more than it would hurt it. I
| personally hope the hacker mentality and the immensely
| perf-driven nature of JavaScript is one day adopted by
| Python.
|
| For those following, I want to make it clear that the
| "bits" being discussed are extremely nuanced and won't
| get in the way of doing obviously useful things in
| JavaScript.
|
| Here's how you create a JS Object from C using Node-API:
| https://nodejs.org/api/n-api.html#napi_create_object
|
| It conforms to ECMAScript 6.1.7 Object Types and is very
| much the same internal representation used by the VM.
|
| Here's how one might tickle the internal representation
| used by Node.js (V8 in this case) to change the value of
| the underlying property of a JavaScript object from C:
| https://nodejs.org/api/n-api.html#napi_set_element
| HenriTEL wrote:
| > I suspect a willingness to break compatibility for the
| sake of performance would benefit the language a lot more
| than it would hurt it
|
| It took a long time for the community to recover from the
| python3 incompatibility with python2. I don't think we
| are ready for another round.
| cogman10 wrote:
| > but I suspect a willingness to break compatibility for
| the sake of performance would benefit the language a lot
| more than it would hurt it.
|
| That's already happen in the form of graalpy and pypy.
| The community has voted and they want compatibility more
| than they want performance.
| amelius wrote:
| > Accessing data in a Python object from c ( and vice
| versa) is trivial. That triviality is what gets in the way
| of JIT optimizations.
|
| Can't it be automated? Accessing data is often done in
| patterns that are very similar.
|
| Perhaps we should access Python from Rust, would that help?
| cogman10 wrote:
| Absolutely, and it usually is. The FFI isn't generally
| hard to use because of the automation.
| kzrdude wrote:
| It's both. Language semantics make it hard to optimize Python,
| even for the runtime / even for a JIT.
| somekyle wrote:
| An underrated factor in this conversation is implementation
| effort. Javascript is arguably the most widely run
| interpreted language in the world. Pre-Chrome, JS was
| uniformly rather slow, but Google was betting on webapps
| being good and usable, so they brought on some top-tier
| compilation/VM talent to build V8. As fast Javascript
| existed, it made it possible to do more natively in the
| browser, and other browser vendors joined in an arms race
| there. Tons of effort overall, tons of money and time from
| top-tier experts.
|
| There was no equivalent competition between major
| organizations to make Python fast. Folks have tried, but not
| on the same scale. Yes, factors like language design and
| existing ecosystems entanglements played a role here, but if
| Python had the investment in performance Javascript had
| (financial and expert attention), it'd be dramatically faster
| today (though it may have required a fork or similar,
| depending on how tied to simplicity Guido was feeling).
|
| To be clear, I'm not saying nobody tried to make Python
| faster, or that Python devs don't know what they're doing. I
| know very well both of those things aren't true. But, the
| kind of sophistication required to make Python fast in
| absolute terms is very hard to build and maintain, and for
| various reasons nobody who has found Python to be too slow
| has found "invest in a bunch of person-years of VM engineer
| attention dedicated to performance work" to be their best
| path.
| williamstein wrote:
| The WebAssembly version of this exact test takes about twice as
| long as running natively. I just happened to do exactly this
| benchmark a few minutes ago:
|
| Python 3.11.0 native: 0m43.755s
|
| Python 3.11.0 WebAssembly (on node.js): 1m31.305s (about 2.1x
| as long).
|
| For what it is worth, I also maintain a Python --> Javascript
| transpiler (https://www.npmjs.com/package/pylang) and I tried
| it on exactly this benchmark (with some very minor changes):
|
| PyLang: 0m19.386s (on node.js) about half as long as Python
| 3.11.0 native
|
| The article uses bun, which uses Safari's JS runtime, which
| sometimes has significantly better performance than node.js for
| these sorts of benchmarks (especially for Webassembly), in my
| experience.
|
| These tests were all on an M1 Macbook Pro.
| outworlder wrote:
| > Is the performance difference of Python and Javascript due to
| the language or due to the runtime?
|
| It's almost always the runtime. Unless the language spec makes
| it particularly difficult to implement a feature in a way
| that's performant while still respecting the spec.
|
| Which is why the discussion on which languages are "faster" is
| seldom productive. Languages are not fast or slow by
| themselves. And, even when they are on average, implementing
| stuff on Assembly is no guarantee of speed. Quite often, higher
| level abstractions lead to optimizations that are difficult to
| replicate if one is operating at a lower level.
|
| As a very trivial example, consider short circuit evaluation.
| It's something that you explicitly have to code in assembly,
| but most languages have implemented out of the box. Or garbage
| collection - allocating and deallocating memory on demand is
| memory efficient, but it's not necessarily what you want to do
| for performance. In many cases, deferring garbage collection
| allows for often-accessed memory to be retained, where as a C
| implementation would be constantly allocating and freeing.
| Fixing that requires programmer effort.
|
| What I think matters the most is the ability of a language
| (+runtime) to access lower layers when needed (ASM blocks in C,
| FFI in Python).
| gpderetta wrote:
| While with enough trust even pigs can fly (witness the heroic
| efforts to make JS fast), some languages are indeed
| inherently faster than others either because the semantics
| are such that they are easier to translate to an actual
| machine efficiently or there is less abstraction between the
| language and the machine.
| DeathArrow wrote:
| >And, even when they are on average, implementing stuff on
| Assembly is no guarantee of speed. Quite often, higher level
| abstractions lead to optimizations that are difficult to
| replicate if one is operating at a lower level.
|
| When browsing Code Golf, most often than not, the fastest
| implementation is in assembler. And sometimes it can be 2x -
| 4x faster than next fastest implementation which usually is
| C++.
___________________________________________________________________
(page generated 2022-10-26 23:01 UTC)