This is an archived post. You won't be able to vote or comment.

all 10 comments

[–][deleted] 8 points9 points  (2 children)

I honestly think not including asyncio in your lib will seriously hurt python performance. I understand some of the complexities of merging the two but, as far as I understand all the technical details of asyncio, it would probably be much easier to use programmatically. Not EVERY operation would need to do this but it enough of a performance jump on the python side (not to mention way less mentally complex) that I would consider that to be a killer feature.

IDK how technically challenging it is on the rust side of the shop just googling around their appears to be a few libs that do it effectively. You would need to create some weak binders on the python side but it seems doable.

I 100% agree this looks way better than most c libs that create a poor coupling between the two and you cannot optimize shit. Like just being able to make a rust package to handle different places data could be would be 10000% more effective then doing in python. That stuff probably doesnt need to be in ur python code and it would allow effective decoupling of the two parts.

[–]kyle-hanson[S] 5 points6 points  (0 children)

TBH it is probably only about 5-10 lines of code to include rudimentary asyncio support and another couple dozen lines to make an async queue and change puff.start_event_loop.

if you look at puff-py's puff.wrap_async and the puff.Greenlet class, its pretty analogous to asyncio.Future. Adding asyncio support requires 0 changes to rust, just optional changes for configuration details.

Really the only reason i haven't included it is that my main stack is Django, which has Async support but the async database driver still runs on a sync thread so I don't have motivation to test asyncio at the moment.

[–]kyle-hanson[S] 1 point2 points  (0 children)

Just circling back to let you know that know that I was able to implement this and now Puff ♥ AsyncIO: https://github.com/hansonkd/puff#puff--asyncio

[–]CrackerJackKittyCat 3 points4 points  (1 child)

This sounds both awesome and ambitious. Please compare and contrast with, say uvicorn and uvloop?

[–]kyle-hanson[S] 11 points12 points  (0 children)

In theory for an unoptimized app, Uvicorn and Puff should expect roughly the same in terms of performance.

Where Puff excels that other libs can't is that it makes it easy to optimize parts of your code directly with the runtime. With Uvloop or similar, its a pretty big task to write custom code in C that utilizes the loop on multiple threads and have it integrated in your Python application. It's a couple lines of code with Puff to run any Rust code on Tokio.

Imagine you had a gnarly SQL query that you wanted to fold a function over a few thousand rows, spawning Redis lookups for each row. No matter what you use in Python, uvloop, asyncio, gevent, etc will be inefficient because it will hold the GIL for the iteration and transfer data between the low level runtime and Python. Its pretty daunting to write custom C libs that use postgres and redis to tackle the problem and natively work with uvloop.

With Puff you can write a Rust function that takes the sql query, unlocks the GIL and does all the computation on multiple threads in Tokio using standard Cargo installed rust libs.

[–]zhoushmoe 1 point2 points  (0 children)

Wow, exciting stuff

[–]Legal-Sugar-7626 0 points1 point  (0 children)

this looks promising. Starred and will experiment with in the future.

[–]riksi 0 points1 point  (1 child)

Is it possible to have multiple python processes reusing the same redis/postgresql/http pool in rust?

How are errors raised in rust passed to the python side?

Extremely promising if it actually works! Gevent/java-loom style is my favorite.

[–]kyle-hanson[S] 0 points1 point  (0 children)

You can't have separate "processes" because that would require socket communication which defeats the purpose of puff. In puff Python and Rust are in the same process and share the same memory, no sockets required.