31 ms·
These speedups are awesome, but of course one wonders why they haven't been a low-hanging fruit over the past 25 years. Having read about some of the changes [
by uniqueuid 4y ago
These speedups are awesome, but of course one wonders why they haven't been a low-hanging fruit over the past 25 years.
Having read about some of the changes [1], it seems like the python core committers preferred clean over fast implementations and have deviated from this mantra with 3.11.
Now let's get a sane concurrency story (no multiprocessing / queue / pickle hacks) and suddenly it's a completely different language!
[1] Here are the python docs on what precisely gave the speedups: https://docs.python.org/3.11/whatsnew/3.11.html#faster-cpython https://docs.python.org/3.11/whatsnew/3.11.html#faster-cpyth...
[edit] A bit of explanation what I meant by low-hanging fruit: One of the changes is "Subscripting container types such as list, tuple and dict directly index the underlying data structures." Surely that seems like a straight-forward idea in retrospect. In fact, many python (/c) libraries try to do zero-copy work with data structures already, such as numpy.
- fastball 4y ago> Now let's get a sane concurrency story This is in very active development[1]! And seems like the Core Team is not totally against the idea[2]. [1] https://github.com/colesbury/nogil https://github.com/colesbury/nogil [2] https://pyfound.blogspot.com/2022/05/the-2022-python-language-summit-python_11.html https://pyfound.blogspot.com/2022/05/the-2022-python-languag...
- siekmanj 4y agoPython has actually had concurrency since about 2019: https://docs.python.org/3/library/asyncio.html https://docs.python.org/3/library/asyncio.html. Having used it a few times, it seems fairly sane, but tbf my experience with concurrency in other languages is fairly limited. edit: ray https://github.com/ray-project/ray https://github.com/ray-project/ray is also pretty easy to use and powerful for actual parallelism
- uniqueuid 4y agoI have used asyncio in anger quite a bit, and have to say that it seems elegant at first and works very well for some use cases. But when you try to do things that aren't a map-reduce or Pool.map() pattern, it suddenly becomes pretty warty. E.g. scheduling work out to a processpool executor is ugly under the hood and IMO ugly syntactically as well.
- tandav 4y ago> scheduling work out to a processpool executor is ugly under the hood and IMO ugly syntactically as well. Are you talking about this example? https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor https://docs.python.org/3/library/asyncio-eventloop.html#asy...
- deleted 4y ago[deleted]
- BugsJustFindMe 4y agoI find asyncio to be horrendous, both because of the silliness of its demands on how you build your code and also because of its arbitrarily limited scope. Thread/ProcessPoolExecutor is personally much nicer to use and universally applicable...unless you need to accommodate Ctrl-C and then it's ugly again. But fixing _that_ stupid problem would have been a better expenditure of effort than asyncio.
- coldtea 4y ago>I find asyncio to be horrendous, both because of the silliness of its demands on how you build your code and also because of its arbitrarily limited scope. Do you compare it to threads and pools, or judge it on its merits as an async framework (with you having experience of those that you think are done better elsewhere, e.g. in Javascript, C#, etc)? Because both things you mention "demands on how you build your code" and "limited scope" are part of the course with async in most languages that aren't async-first.
- BugsJustFindMe 4y ago> Because both things you mention "demands on how you build your code" and "limited scope" are part of the course with async in most languages I don't see how "asyncio is annoying and can only be used for a fraction of scenarios everywhere else too, not just here" is anything other than reinforcement of what I said. OS threads and processes already exist, can already be applied universally for everything, and the pool executors can work with existing serial code without needing the underlying code to contort itself in very fundamental ways. Python's version of asyncio being no worse than someone else's version of asyncio does not sound like a strong case for using Python's asyncio vs fixing the better-in-basically-every-way concurrent futures interface that already existed.
- coldtea 4y ago>I don't see how "asyncio is annoying and can only be used for a fraction of scenarios everywhere else too, not just here" is anything other than reinforcement of what I said. Well, I didn't try to refute what you wrote (for one, it's clearly a personal, subjective opinion). I asked what I've asked merely to clarify whether your issue is with Python's asyncio (e.g. Python got it wrong) or with the tradeoffs inherent in async io APIs in general (regardless of Python). And it seems that it's the latter. I, for one, am fine with async APIs in JS, which have the same "problems" as the one you've mentioned for Python's, so don't share the sentiment.
- fastball 4y agoasyncio is still single-threaded due to the GIL.
- siekmanj 4y agoTrue, but it's not trying to be multi-threaded, just concurrent.
- ikinsey 4y agoWhile not ideal, this can be mitigated with multiprocessing. Python asyncio exposes interfaces for interacting with multiple processes [1]. [1] https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.loop.run_in_executor https://docs.python.org/3/library/asyncio-eventloop.html#asy...
- sgtlaggy 4y agoConcurrency in Python is a weird topic, since multiprocessing is the only "real" concurrency. Threading is "implicit" context switching all in the same process/thread, asyncio is "explicit" context switching. On top of that, you also have the complication of the GIL. If threads don't release the GIL, then you can't effectively switch contexts.
- dragonwriter 4y ago> Concurrency in Python is a weird topic, since multiprocessing is the only "real" concurrency. You are confusing concurrency and parallelism. > Threading is "implicit" context switching all in the same process/thread No, threading is separate native threads but with a lock that prevents execution of Python code in separate threads simultaneously (native code in separate threads, with at most on running Python, can still work.)
- hn_saver 4y agoThreading IS concurrency. When you say "real" concurrency, you actually mean parallelism.
- bornfreddy 4y agoNot in CPython it isn't. Threading in CPython doesn't allow 2 threads to run concurrently (because of GIL). As GP correctly stated, you need multiprocessing (in CPython) for concurrency.
- bulatb 4y agoThey're emphasizing a precise distinction between "concurrent" (the way it's structured) and "parallel" (the way it runs). Concurrent programs have multiple right answers for "Which line of computation can make progress?" Sequential execution picks one step from one of them and runs it, then another, and so on, until everything is done. Whichever step is chosen from whichever computation, it's one step per moment in time; concurrency is only the ability to choose. Parallel execution of concurrent code picks steps from two or more computations and runs them at once. Because of the GIL, Python on CPython has concurrency but limited parallelism.
- dekhn 4y agoAsyncio violates every aspect of compositional orthogonality just like decorators you can't combine it with anything else without completely rewriting your code around its constrictions. It's also caused a huge amount of pip installation problems around the AWS CLI and boto
- Joker_vD 4y agoHaving both Task and Future was a pretty strange move; and the lack of static typing certainly doesn't help: the moment you get a Task wrapping another Task wrapping the actual result, you really want some static analysis tool to tell you that you forgot one "await".
- stepanhruda 4y agoI’m a fan of asyncio, the parent probably meant to say parallelism though, since that’s what getting rid of GIL unlocks.
- ikinsey 4y agoI love asyncio! It's a very well put together library. It provides great interfaces to manage event loops, io, and some basic networking. It gives you a lot of freedom to design asynchronous systems as you see fit. However, batteries are not included. For example, it provides no HTTP client/server. It doesn't interop with any synchronous IO tools in the standard library either, making asyncio a very insular environment. For the majority of problems, Go or Node.js may be better options. They have much more mature environments for managing asynchrony.
- 1337shadow 4y agoIt depends how you see it https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/ https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
- ikinsey 4y agoThis is exactly why Go is a better option for async use cases.
- int_19h 4y agoUntil you need to do async FFI. Callbacks and the async/await syntactic sugar on top of them compose nicely across language boundaries. But green threads are VM-specific.
- notpushkin 4y agoIt does indeed, but personally, I believe with async/await the main pain point of this post (callback hell) is essentially gone.
- MrYellowP 4y agoI don't wonder. For me it seems pretty clear. I believe the reason is that python does not need any low-hanging fruits to have people use it, which is why they're a priority for so many other projects out there. Low-hanging fruits attract people who can't reach higher than that. When talking about low-hanging fruits, it's important to consider who they're for. The intended target audience. It's important to ask ones self who grabs for low-hanging fruits and why they need to be prioritized. And with that in mind, I think the answer is actually obvious: Python never required the speed, because it's just so good. The language is so popular, people search for and find ways around its limitations, which most likely actually even increases its popularity, because it gives people a lot of space to tinker in.
- uniqueuid 4y agoI see your point, but it directly conflicts with the effort many people put into producing extremely fast libraries for specific purposes, such as web frameworks (benchmarked extensively), ORMs and things like json and date parsing, as seen in the excellent ciso8601 [1] for example. [1] https://github.com/closeio/ciso8601 https://github.com/closeio/ciso8601
- dagmx 4y agoI disagree that it conflicts. There's an (implied) ceiling on Python performance, even after optimizations. The fear has always been that removing the design choices that cause that ceiling, would result in a different, incompatible language or runtime. If everyone knows it's never going to reach the performance needed for high performance work, and there's already an excellent escape hatch in the form of C extensions, then why would people be spending time on the middle ground of performance? It'll still be too slow to do the things required, so people will still be going out to C for them. Personally though, I'm glad for any performance increases. Python runs in so much critical infrastructure, that even a few percent would likely be a considerable energy savings when spread out over all users. Of course that assumes people upgrade their versions...but the community tends to be slow to do so in my experience.
- mywittyname 4y ago
- KptMarchewa 4y agoAnswer is very simple. Amount of people who got paid to make python fast was rounded to 0.
- dekhn 4y agoNot really. There were a couple engineers working at Google on a project called unladen swallow which was extremely promising but it eventually got canceled. The developer who worked at Microsoft to make iron python I think that was his full-time project as well and it was definitely faster than cpython at the time
- pstrateman 4y agoNeither of those projects were ever going to be accepted upstream though.
- dekhn 4y agoMy hope was that iron pythonreplaced cpython as the standard but for a number of reasons that was never to be.
- switch007 4y agoWas the project run by a team based in Africa or Europe?
- dekhn 4y agoI don't know! [Whoosh]
- dragonwriter 4y agoThose people were not being paid to speed up CPython, though, but mostly-source-compatible (but not at all native extension compatible) alternative interpreters.
- coldtea 4y ago
- missblit 4y agoSo we have: * Statically allocated ("frozen") core modules for fast imports * Avoid memory allocation for frames / faster frame creation * Inlined python functions are called in pure python without needing to jump through C * Optimizations that take advantage of speculative typing (Reminds me of Javascript JIT compilers -- though according to the FAQ Python isn't JIT yet) * Smaller memory usage for frames, objects, and exceptions Dang that certainly does sound like low hanging fruit. There's probably a lot more opportunities left if they want Python to go even faster.
- dagmx 4y agoThings may seem like low hanging fruit in the abstract bullet point, but the work needed may be immense.
- FartyMcFarter 4y ago> Inlined python functions are called in pure python without needing to jump through C Given that Python is interpreted, it's quite unclear what this could mean. Also, what does it mean to "call" an inlined function?? Isn't the point of inline functions that they don't get called at all?
- liuliu 4y agoIt seems to be just previously, it does: switch (op) { case "call_function": interpret(op.function) ... } Now it does: switch (op) { case "call_function": ... setup frame objects etc ... pc = op.function continue .... } Not sure if they just "inlined" it or use tail-call elimination trick.
- enragedcacti 4y agoIt's a little confusing but I don't think they meant inlining in the traditional sense. its more like they inlined the C function wrapper around python functions. > During a Python function call, Python will call an evaluating C function to interpret that function’s code. This effectively limits pure Python recursion to what’s safe for the C stack. > In 3.11, when CPython detects Python code calling another Python function, it sets up a new frame, and “jumps” to the new code inside the new frame. This avoids calling the C interpreting function altogether. > Most Python function calls now consume no C stack space. This speeds up most of such calls. In simple recursive functions like fibonacci or factorial, a 1.7x speedup was observed. This also means recursive functions can recurse significantly deeper (if the user increases the recursion limit). We measured a 1-3% improvement in pyperformance.
- Alex3917 4y ago> Of course one wonders why they haven't been a low-hanging fruit over the past 25 years. Because it's developed and maintained by volunteers, and there aren't enough folks who want to spend their volunteer time messing around with assembly language. Nor are there enough volunteers that it's practical to require very advanced knowledge of programming language design theory and compiler design theory as a prerequisite for contributing. People will do that stuff if they're being paid 500k a year, like the folks who work on v8 for Google, but there aren't enough people interested in doing it for free to guarantee that CPpython will be maintained in the future if it goes too far down that path. Don't get me wrong, the fact that Python is a community-led language that's stewarded by a non-profit foundation is imho its single greatest asset. But that also comes with some tradeoffs.
- mgaunard 4y agofirst, there are lots of volunteers that want to mess with assembly language. second, CPython is just a C interpeter, there isn't much assembly if any. third, contributing to CPython is sufficiently high-profile you could easily land a 500k-job just by putting it on your CV. No, those are not the real reasons why it hasn't happened before.
- int_19h 4y ago> one wonders why they haven't been a low-hanging fruit over the past 25 years. From the very page you've linked to: "Faster CPython explores optimizations for CPython. The main team is funded by Microsoft to work on this full-time. Pablo Galindo Salgado is also funded by Bloomberg LP to work on the project part-time."
- ChuckNorris89 4y agoHmm, looks like corporate money gets sh*t done.
- deleted 4y ago[deleted]
- lmm 4y agoYep. That's the thing about the open source dream; especially for work like this that requires enough time commitment to understand the whole system, and a lot of uninteresting grinding details such that very few people would do it for fun, you really need people being funded to work on it full-time (and a 1-year academic grant probably doesn't cut it), and businesses are really the only source for that.
- simias 4y agoI suspect that the amount of people and especially companies willing to spend time and money optimizing Python are fairly low. Think about it: if you have some Python application that's having performance issues you can either dig into a foreign codebase to see if you can find something to optimize (with no guarantee of result) and if you do get something done you'll have to get the patch upstream. And all that "only" for a 25% speedup. Or you could rewrite your application in part or in full in Go, Rust, C++ or some other faster language to get a (probably) vastly bigger speedup without having to deal with third parties.
- ketralnis 4y ago> you can either dig into a foreign codebase ... > Or you could rewrite your application Programmers love to save an hour in the library by spending a week in the lab
- prionassembly 4y agoEveryone likes to shirk away from their jobs; engineers and programmers have ways of making their fun (I'm teaching myself how to write parsers by giving each project a DSL) look like work. Lingerie designers or eyebrow barbers have nothing of the sort, they just blow off work on TikTok or something.
- fragmede 4y agoTikTok’s got some fun coding content, if you can get the algorithm to surface it to you.
- LtWorf 4y agoThere was some guarantee of result. It has been a long process but there was mostly one person who had identified a number of ways to make it faster but wanted financing to actually do the job. Seems Microsoft is doing the financing, but this has been going on for quite a while.
- dubbel 4y agoYou are right, that's usually not how it works. Instead, there are big companies, who are running let's say the majority of their workloads in python. It's working well, it doesn't need to be very performant, but together all of the workloads are representing a considerable portion of your compute spend. At a certain scale it makes sense to employ experts who can for example optimize Python itself, or the Linux kernel, or your DBMS. Not because you need the performance improvement for any specific workload, but to shave off 2% of your total compute spend. This isn't applicable to small or medium companies usually, but it can work out for bigger ones.
- Jasper_ 4y ago> one wonders why they haven't been a low-hanging fruit over the past 25 years Because the core team just hasn't prioritized performance, and have actively resisted performance work, at least until now. The big reason has been about maintainership cost of such work, but often times plenty of VM engineers show up to assist the core team and they have always been pushed away. > Now let's get a sane concurrency story You really can't easily add a threading model like that and make everything go faster. The hype of "GIL-removal" branches is that you can take your existing threading.Thread Python code, and run it on a GIL-less Python, and you'll instantly get a 5x speedup. In practice, that's not going to happen, you're going to have to modify your code substantially to support that level of work. The difficulty with Python's concurrency is that the language doesn't have a cohesive threading model, and many programs are simply held alive and working by the GIL.
- dekhn 4y agoYup. Sad but true. I just wanted c++ style multithreading with unsafe shared memory but it's too late. I was impressed by the recent fork that addresses this in a very sophisticated way, but realistically gil cpython will keep finding speed ups to stave off the transition.
- staticassertion 4y agoGuido stepping away from the language will have a lot of impact on changes that were culturally guided.
- mjw1007 4y agoGuido is one of the people leading the current performance efforts.
- staticassertion 4y agoThat's interesting. Thanks.
- deleted 4y ago[deleted]
- gostsamo 4y agoA few people tried to excuse the slow python, but as far as I know the story, excuses are not necessary. Truth is that python was not meant to be fast, its source code was not meant to be fast, and its design was not optimized with the idea of being fast. Python was meant as a scrypting language that was easy to learn and work with on all levels and the issue of its slowness became important when it outgrew its role and became an application language powering large parts of the internet and the bigger part of the very expensive ML industry. I know that speed is a virtue, but it becomes a fundamental virtue when you have to scale and python was not meant to scale. So, yes, it is easy for people to be righteous and furious over the issue, but being righteous in hindsight is much easier than useful.
- atwood22 4y ago> Python was meant as a scrypting language that was easy to learn and work with on all levels. Being fast isn't contradictory with this goal. If anything, this is a lesson that so many developers forget. Things should be fast by default.
- BeetleB 4y ago> Things should be fast by default. In over 90% of my work in the SW industry, being fast(er) was of no benefit to anyone. So no, it should not be fast by default.
- vorticalbox 4y agoBeing first to market is usually more important than being faster then those who got there first.
- uoaei 4y agoHa! Good luck convincing end-users that that's true.
- BeetleB 4y agoI don't need to. Less than 10% of end users have put in requests for performance improvements.
- Fiahil 4y ago> Now let's get a sane concurrency story (no multiprocessing / queue / pickle hacks) and suddenly it's a completely different language! Yes, and I would argue it already exists and is called Rust :) Semi-jokes aside, this is difficult and is not just about removing the GIL and enabling multithreading ; we would need to get better memory and garbage collection controls. Parts of what's make python slow and dangerous in concurrent settings are the ballooning memory allocations on large and fragmented workloads. A -Xmx would help.
- oaiey 4y agoThere is a race right now to be more performant. .NET, Java, Go already participate, Rust/C++ are anyway there. So to stay relevant they have to start participate. .NET went through the same some years ago. And why they were not addressed: because starting a certain points, the optimization are e.g. processor specific or non intuitive to understand. Making it hard to maintain vs a simple straight forward solution.
- tambourine_man 4y agoThat’s something that has always puzzled me as well. Given the popularity, you’d think Python would have had several generations of JITs by now and yet it still runs interpreted, AFAIK. JavaScript has proven that any language can be made fast given enough money and brains, no matter how dynamic. Maybe Python's C escape hatch is so good that it’s not worth the trouble. It’s still puzzling to me though.
- dragonwriter 4y ago> JavaScript has proven that any language can be made fast given enough money and brains, Yeah but commercial Smalltalk proved that a long time before JS did. (Heck, back when it was maintained, the fastest Ruby implementation was built on top of a commercial Smalltalk system, which makes sense given they have a reasonably similar model.) The hard part is that “enough money“ is...not a given, especially for noncommercial projects. JS got it because Google decided JavaScript speed was integral to it's business of getting the web to replace local apps. Microsoft recently developed sufficient interest in Python to throw some money at it.
- tambourine_man 4y agoYes, I’m aware of the Smalltalk miracle. Google wasn’t alone in optimizing JS, it actually came late, Safari and Firefox were already competing and improving their runtime speeds, though V8 did doubled down on the bet of a fast JS machine. The question is why there isn’t enough money, given that there obviously is a lot of interest from big players.
- dragonwriter 4y ago> The question is why there isn’t enough money, given that there obviously is a lot of interest from big players. I'd argue that there wasn't actually much interest until recently, and that's because it is only recently that interest in the CPython ecosystem has intersected with interest in speed that has money behind it, because of the sudden broad relevance to commercial business of the Python scientific stack for data science. Both Unladen Swallow and IronPython were driven by interest in Python as a scripting language in contexts detached from, or at least not necessarily attached to, the existing CPython ecosystem.
- Sesse__ 4y agoBecause Guido van Rossum just isn't very good with performance, and when others tried to contribute improvements, he started heckling their talk because he thought they were “condescending”: https://lwn.net/Articles/754163/ https://lwn.net/Articles/754163/ And by this time, we've come to the point where the Python extension API is as good as set in stone. Note that all of the given benchmarks are microbenchmarks; the gains in 3.11 are _much_ less pronounced on larger systems like web frameworks.
- emmelaich 4y agoPerhaps they took a lesson from Perl; its code base was so complex as to be near unmaintainable. In addition to the other point here about speed not being a target in the first place.