-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Threading backend? #12
Comments
I have thought a bit about a threading backend and haven't implemented it yet for a few reasons:
I'm curious about your feedback on these issues. If you feel a threading backend has value, it would probably not be much work to add in. |
So it turns out this is really difficult. Without any ability to control the interpreter's thread scheduler, there's not much we can do. |
Yeah, well, I've been experimenting with threading + gevent for a while (I have a feed fetcher working atop that). In my experience, Go is stupefyingly performant precisely because its scheduler maps OS threads to goroutines, and that's why I was looking at offset -- it implements a scheduler like Go's. |
But I still don't see what the upside is for Python code? You can't achieve parallelism anyway due to the GIL, so the "juggle goroutines across OS threads" model doesn't help at all. Assuming there's no IO, simply using goless with its stackless backend (Stackless or PyPy) and a single thread is going to give better CPU performance than any sort of scheduler and multiple threads. Switching threads in Python is not cheap. I'm not sure I see the upside of a threading-based backend. Which reminds me, we should probably abstract the monkeypatching capabilities of gevent and stackless (stacklesslib) into goless. |
In my testing, the GIL is not really an issue when you're fetching and parsing hundreds of feeds. Python can take advantage of multiple cores just fine, and using threads does provide better performance -- it all depends on your workload and how far each thread can progress independently. Of course, I don't expect Python to outperform Go on this, just saying that threading is useful and does help. |
@rcarmo """the GIL is not really an issue when you're fetching and parsing hundreds of feeds.""" If that is true, then you don't need more than one thread, and your whole point is nonsense, Please don't emit such statements without proof if you are after a real discussion. |
My bottle-fever project, for starters, which is stalled on Github but evolved (elsewhere) into a larger scale affair. That and a couple of years doing work with Celery, the last of which involved a few tens of millions of task runs across a few dozen cores on multiple machines using a mix of threaded and gevent workers. So yes, I do know what I'm talking about. And I honestly don't appreciate that kind of retort when I'm discussing an issue, so kindly dial it down... I'm interested in goless for its simplicity and promise, but technical merits are not the only reason one gets involved... or not.
|
I appreciate your experience with your other projects, also using Celerity, ZeroMQ Thanks - tismer at stackless.com |
@rcarmo I am a bit confused by some claims. I am going to quote each thing I have questions about:
No question, because for the most part you are just waiting for IO.
I am most confused by this claim. Unless you are working with C extensions that do not need the GIL (or using something like PyParallel), I would need more explanation how this can be the case. A Python-only CPython program cannot use more than one core at a time (though I suspect it can use different cores if you use multiple threads, but only one is running at a time).
This cannot be the case. There is overhead with thread scheduling at the interpreter level, not to mention things like context switching. David Beasly has a great presentation about the GIL that you may have seen. If only one thread can run at a time (see last point), multiple threads will always increase overall CPU time.
Actually with PyPy I wonder if it can compete against Go :) At least in a single-threaded environment. And perhaps the goless model will benefit from STM very much, with minimal shared memory. I will add an issue to add some Go benchmarks. Really, being programmers, the best solution would be to provide some code that demonstrates what you are talking about! (Python using multiple cores, threads improving performance). |
I've had mixed experiences with PyPy, largely because most of what I use Python for is either server-side web stuff (where string manipulation and object access slow it down significantly) or IO-bound stuff where it delivers very little improvement (and where threading is a quick way to leverage multiple cores). When I need proper concurrency, I usually dip into the JVM (or, lately, Go). |
Would still love feedback on the rest of my questions, if we want to go any further with this. |
Aaand I'm back. I think you'll be pleased to know that goless is now being used for a few message-handling chores down at my neck of the woods, but getting back to the topic at hand, the recent pypy-stm alpha (which I'm testing) would probably be a nice target for a threading backend. |
I am very pleased! 👍 Will do my best to take care of anything that comes up and keep things stable. The way I see it there are a few options:
Thoughts? |
Well, 3) seems a lot like the Go scheduler (and I recall some discussion about that in the |
Links, fyi. If they get the donations [3] do you think that functionality would be sufficient? The current docs [1] discuss problems currently with being conflict-prone. 1.[]Docs for Software Transactional Memory — PyPy 2.4.0 documentation |
Having a STM implementation wouldn't be enough (and I'm confident PyPy team will come up with one though). You also need a multithreaded program. goless would work for free if a) PyPy had STM and b) they updated their Go-style concurrency is a good candidate for STM because shared memory (what creates conflicts) is an antipattern there. I'd be excited for someone to take up this work (forking goless, or just copy/pasting stuff into a new codebase focused on STM). I do not have the time, unfortunately, since I'm not using Python at work currently. |
Thank you @rgalanakis . So am I misreading it? It seems like the proposed Pypy-Stm does have or plan to have multithreading, and stackless.py is part of pypy so it should come too, right? Both the docs and the latest release notes imply that to me. Of course , it's not funded yet so there's alot of uncertainty. Docs; Release; |
stackless.py is "part" of pypy but not its core. For example it doesn't work in PyPy3. And it (well, continulets) would still need work to take advantage of STM. My point is, mostly, that a good threading backend with STM support (IMO the only reason to create a threading backend) would require lower-level scheduler work than goless was designed for. Remember that goless isn't rewriting Go in Python, it's really just a wrapper to allow go-like programming on top of Python libraries/runtimes that allow asynchrony. Once such a scheduler system was built, goless could just have another adapter/backend written for it, like it can swap between gevent/stackless. But this work is quite outside goless (though it could be done with goless in mind). |
Incidentally, I hacked my threaded task queue to support a goless-like syntax: https://github.com/rcarmo/python-utils/blob/master/taskkit.py Bear in mind that this was originally something designed to let me run Celery-like code without the hassle of installing a message queue (hence the scheduler thread, priorities and retry support), but it now lets me write goless-like code for systems where I can't install gevent and seems to work fairly well with PyPy (I have a tiny RADIUS server that handles accounting events, sends the interesting ones down a couple of channels to specific workers that do HTTP requests for lookups and a few more chained tasks that take the results and apply further processing). All of it mostly I/O bound and relatively simple, but at least it's now vastly more readable... |
Have you tried writing a goless backend for it? |
I don't think it would be a very clean fit as it is. I've never been happy with my scheduler, for starters, and I'm likely to rewrite the whole thing some day and split the "mini-Celery" bits away from the "goish" bits. It's a hack atop another hack, and even if adding Besides, I'm writing a fair amount of Go and Clojure these days... |
Maybe a threading backend could make use of https://github.com/stuglaser/pychan which supports python3 now. |
This is great, and much nicer than my homegrown threading solution. How difficult would it be to mix in a threading back-end?
The text was updated successfully, but these errors were encountered: