Can someone explain how it works under the hood. A Rust server for python obviously needs to still run the python interpreter. Is it running many instances to get around the GIL, and doing the request management / reverse proxy / runtime management in rust?
I'm confused, in the example application I see all these async endpoints interacting with the database, but the function bodies are entirely sync. Wouldn't this block the event loop?
Presumably, they would - hopefully, the work they're doing is quick enough that it doesn't really matter that they're blocking (this is usually true when interacting with sqlite, for example). Async request handlers are nice to have for when you do want to do something genuinely async (like firing off another HTTP request to somewhere else)
To GP: yes, it would block the event loop and that's pretty bad. But...
asyncio.to_thread[0] as a quick workaround, just keep track of your thread count. Obviously frameworks and libraries with asyncio support should be chosen whenever possible.
> Overall there are also places where functions are async running in sync bodies, but they're not running on main thread.
That would be a design mistake, as functions have colors[1] with async/await. That's currently my biggest gripe in the python ecosystem, apart from modules maintaining their own hidden state.
Especially over Flask and Django, Robyn additionally offers integrated websocket support along with many existing features like templating, logging etc.[1]
Developer has been working on this project for a few years now, here is the updated roadmap, shared by the developer and maintainer of the project.[2]
Based on the [1] one of the obvious places where Robyn comes at top is in terms of latency of Websockets and OpenAPI Docs generation. I've tagged the author for a detailed response.
golang has frameworks like gin that are faster and simpler when building barebones apps, the more features you need the more modules increase. Robyn brings all the features out of the box, I know it's a compromise but a good one over eventual complexity of the application in the long term.
If you hate Python so much you need to replace the linters, package managers, and now Web frameworks with Rust, why not just go all the way and write everything in Rust?
Python's success is partly because it is easy to do things. It has a huge market share. Combining the speed advantage of one programming language, with another seems like a great idea.
Is it really going to be faster? In the benchmark they cited in the README [0], they are in 10th place among Python frameworks. This is not a real-life benchmark, as it merely expects a hardcoded response. In fact, Robyn’s 10th place is thanks to a feature designed for benchmarks like this, i.e. marking responses as constant [1]. Three more frameworks beat Robyn if you disable this benchmark optimization.
Can't speak for Robyn since that is competing in an already aggressively competitive landscape (webserving). Whereas introduction of RUFF/UV by astral has been exceptional.
The problem with all this combining is that it's making apps less portable. Like I want to make apps that work on desktop+mobile with flet[0], but now I have to specifically seek out more "traditional" alternate packages and hope they stayed in reasonable feature parity with these Rustified Frankensteins. Not a fan at all.
Correct me if I'm wrong, but the way you use "traditional", basically means "written in C", right? I certainly can sympathize with your point about the frustration of compatibility issues in your narrow usecase (though I don't agree that it should affect what options we have), but connecting to the original commenter's point, it's really common for libraries in python to be wrappers for things written in other languages.
The use case isn't that narrow though. Just the flet project has 12.5k GH stars (which I would say represents significant adoption), and I'll wager there are other projects out there running in random environments that have Python support but bringing in Rust will be a serious pain. It's degrading the ecosystem IMO. The only other language I'm aware of that has significant library wrapping is Fortran, and those libraries have on par or better alternatives in C as well as are now essentially legacy.
There’s native modules to speed up hot paths, and there’s writing 29% [0] of your framework in Rust, entirely sidestepping interoperability standards, like ASGI.
[0] https://github.com/sparckles/Robyn says 50% Python, 25.3% JS, 20.7% Rust — but all the JS code seems to be for their docs site, so it is reasonable to say 20.7 / 70.7 = 29.2% is in Rust.
Careful now. That kind of provocative black-and-white claim will only alienate the 50.1% of American voters who appreciate Mr Joker’s anti-government and anti-woke agenda.
Why do all those micro framework copy the worst aspects of flask?
The global request object, the bad integration with sqlalchemy, the strong coupling with an application object that forced the indirection of blueprints...
If you start again from scratch, forcing people to migrate their stack and therefor leave their ecosystem behind, at least fix the glaring API problems.
The biggest differentiator between Robyn and frameworks like FastAPI or Sanic seems to be the Rust runtime. But is Python's async actually the bottleneck that Rust is solving here?
Actual bottleneck in examples is sqlalchemy, like 10x overhead easily. I find it quite funny. There is no real difference in web frameworks for real apps in terms of overhead.
I hear this sort of thinking repeated often, and it makes sense at an intuitive level.
However, my experience is that this isn’t always the case. My company has a medium-large Python web app in production, and having viewed performance profiles, I can say definitively that Python code execution occupies a non-trivial amount of processing time. Of course the single largest time sink is the LLM requests we make, but if we could magically nullify the Python processing time, our latency would significantly improve.
The culprit in this case may be specific to FastAPI and Pydantic rather than Python generally, but the point still holds that not all web frameworks and resultant apps are equivalent.
That said, I’ve been dreaming of rewriting large chunks of it in golang. I’ve always known Python was relatively slower than other languages, but I saw a recent benchmark measuring golang as 50x faster than Python. Perhaps the benchmark won’t translate to real world performance, but still - 50x is difficult to ignore.
Returning static "hello world" response for slowest python framework is easily not bigger than 1ms (for fast frameworks it's 0.1ms or lower). Good luck to make the rest of your app to make something comparably fast if db or network is involved.
Can someone explain how it works under the hood. A Rust server for python obviously needs to still run the python interpreter. Is it running many instances to get around the GIL, and doing the request management / reverse proxy / runtime management in rust?
https://pyo3.rs/
I'm confused, in the example application I see all these async endpoints interacting with the database, but the function bodies are entirely sync. Wouldn't this block the event loop?
Presumably, they would - hopefully, the work they're doing is quick enough that it doesn't really matter that they're blocking (this is usually true when interacting with sqlite, for example). Async request handlers are nice to have for when you do want to do something genuinely async (like firing off another HTTP request to somewhere else)
It looks like the author is mistakenly using the sync versions of SQLAlchemy calls. Unless it's on purpose. Either way, not a good sign.
Based on my experience.
At some places where there were no better alternatives, framework utilizes sync functions under the hood, such as some databases.
Overall there are also places where functions are async running in sync bodies, but they're not running on main thread.
To GP: yes, it would block the event loop and that's pretty bad. But...
asyncio.to_thread[0] as a quick workaround, just keep track of your thread count. Obviously frameworks and libraries with asyncio support should be chosen whenever possible.
> Overall there are also places where functions are async running in sync bodies, but they're not running on main thread.
That would be a design mistake, as functions have colors[1] with async/await. That's currently my biggest gripe in the python ecosystem, apart from modules maintaining their own hidden state.
[0]: https://docs.python.org/3/library/asyncio-task.html#asyncio....
[1]: https://journal.stuffwithstuff.com/2015/02/01/what-color-is-...
It looks like a nice design! I'd love to hear a bit more about what it offers over Django/Flask/FastAPI though!
The examples look very similar to Fast API and the requests per second comparisons make Robyn look very speedy![0]
I'm sure the developer has more of a vision than just "faster fast api" though - would love to hear more!
[0] https://github.com/sparckles/robyn
Especially over Flask and Django, Robyn additionally offers integrated websocket support along with many existing features like templating, logging etc.[1]
Developer has been working on this project for a few years now, here is the updated roadmap, shared by the developer and maintainer of the project.[2]
[1] https://robyn.tech/documentation/en
[2] https://github.com/sparckles/Robyn/issues/1001
So it's intended to be a "faster fast api"?
it's much faster for development and prototyping to production, because:
- doesn't require any external ASGI in Prod
- has in-built CORS
- Rust runtime
in my opinion
- FastAPI doesn't require any external ASGI in prod either ever since they added the fastapi cli.
- FastAPI has built-in CORS. Has for years. I don't remember it ever not having.
I don't see how Robyn is faster for development and prototyping.
You can't compare this to Django at all.
It looks similar in concept to Flask and Fast API (Likely with a speed advantage), and duplicating their features it feasible.
It is not comparable to Django.
would be nice to know from the author how this compares to granian
Based on the [1] one of the obvious places where Robyn comes at top is in terms of latency of Websockets and OpenAPI Docs generation. I've tagged the author for a detailed response.
[1] https://github.com/emmett-framework/granian
By looking at the “File Upload” example: https://robyn.tech/documentation/en/api_reference/file-uploa.... Robyn is subject to DoS. While it may be fast but it seems poorly designed. This day and age should use a "reader" concept like Go.
It having types makes me accept the Python bit. I'd still rather go for something in golang though, hard to beat it for web servers.
golang has frameworks like gin that are faster and simpler when building barebones apps, the more features you need the more modules increase. Robyn brings all the features out of the box, I know it's a compromise but a good one over eventual complexity of the application in the long term.
which part of this framework is Batman inspired?
It'll be orphaned as a child.
BAM! BONK! POW! BLAP!
If you hate Python so much you need to replace the linters, package managers, and now Web frameworks with Rust, why not just go all the way and write everything in Rust?
Python's success is partly because it is easy to do things. It has a huge market share. Combining the speed advantage of one programming language, with another seems like a great idea.
Is it really going to be faster? In the benchmark they cited in the README [0], they are in 10th place among Python frameworks. This is not a real-life benchmark, as it merely expects a hardcoded response. In fact, Robyn’s 10th place is thanks to a feature designed for benchmarks like this, i.e. marking responses as constant [1]. Three more frameworks beat Robyn if you disable this benchmark optimization.
[0] https://www.techempower.com/benchmarks/#hw=ph&test=plaintext...
[1] https://robyn.tech/documentation/en/api_reference/const_requ...
Can't speak for Robyn since that is competing in an already aggressively competitive landscape (webserving). Whereas introduction of RUFF/UV by astral has been exceptional.
The problem with all this combining is that it's making apps less portable. Like I want to make apps that work on desktop+mobile with flet[0], but now I have to specifically seek out more "traditional" alternate packages and hope they stayed in reasonable feature parity with these Rustified Frankensteins. Not a fan at all.
[0] https://flet.dev
Correct me if I'm wrong, but the way you use "traditional", basically means "written in C", right? I certainly can sympathize with your point about the frustration of compatibility issues in your narrow usecase (though I don't agree that it should affect what options we have), but connecting to the original commenter's point, it's really common for libraries in python to be wrappers for things written in other languages.
The use case isn't that narrow though. Just the flet project has 12.5k GH stars (which I would say represents significant adoption), and I'll wager there are other projects out there running in random environments that have Python support but bringing in Rust will be a serious pain. It's degrading the ecosystem IMO. The only other language I'm aware of that has significant library wrapping is Fortran, and those libraries have on par or better alternatives in C as well as are now essentially legacy.
Hasn’t Python had native modules for eons now? How is this any different?
There’s native modules to speed up hot paths, and there’s writing 29% [0] of your framework in Rust, entirely sidestepping interoperability standards, like ASGI.
[0] https://github.com/sparckles/Robyn says 50% Python, 25.3% JS, 20.7% Rust — but all the JS code seems to be for their docs site, so it is reasonable to say 20.7 / 70.7 = 29.2% is in Rust.
Fascinating that the website requires more js than they use rust on the actual framework.
What is Batman? My Google skills are failing
Batman is the secret identity of Bruce Wayne
Thanks for the spoiler, I was just about to start
While I am at it, did not see it coming, but towards the end the twist is that Joker is the bad guy.
Once you know and rewatch it you see all these subtle clues along the way.
Careful now. That kind of provocative black-and-white claim will only alienate the 50.1% of American voters who appreciate Mr Joker’s anti-government and anti-woke agenda.
my guess would be batman.js
The CoffeeScript rails clone? Seems an unlikely inspiration for this
I think it means actual Batman. The web dev who uses this framework is encouraged to roleplay Batman.
https://robyn.tech/documentation/en/api_reference/advanced_f...
The comic book hero
[dead]
Why do all those micro framework copy the worst aspects of flask?
The global request object, the bad integration with sqlalchemy, the strong coupling with an application object that forced the indirection of blueprints...
If you start again from scratch, forcing people to migrate their stack and therefor leave their ecosystem behind, at least fix the glaring API problems.
The biggest differentiator between Robyn and frameworks like FastAPI or Sanic seems to be the Rust runtime. But is Python's async actually the bottleneck that Rust is solving here?
Actual bottleneck in examples is sqlalchemy, like 10x overhead easily. I find it quite funny. There is no real difference in web frameworks for real apps in terms of overhead.
There are wider performance gaps between Python-based frameworks and things like using Rust+Axum or Go.
I hear this sort of thinking repeated often, and it makes sense at an intuitive level.
However, my experience is that this isn’t always the case. My company has a medium-large Python web app in production, and having viewed performance profiles, I can say definitively that Python code execution occupies a non-trivial amount of processing time. Of course the single largest time sink is the LLM requests we make, but if we could magically nullify the Python processing time, our latency would significantly improve.
The culprit in this case may be specific to FastAPI and Pydantic rather than Python generally, but the point still holds that not all web frameworks and resultant apps are equivalent.
That said, I’ve been dreaming of rewriting large chunks of it in golang. I’ve always known Python was relatively slower than other languages, but I saw a recent benchmark measuring golang as 50x faster than Python. Perhaps the benchmark won’t translate to real world performance, but still - 50x is difficult to ignore.
I've often wondered about this; are there studies/tests to this effect anywhere that you can link?
Returning static "hello world" response for slowest python framework is easily not bigger than 1ms (for fast frameworks it's 0.1ms or lower). Good luck to make the rest of your app to make something comparably fast if db or network is involved.
Global Interpreter Lock (GIL) limits how effectively multiple threads can be used in Python.
Hence the event loop in Rust runtime for async makes more sense here.
An async event loop doesn't have anything to do with the GIL or threads.
Async is all about cooperative concurrency where a task yields in places that it would normally block. The tasks can all run in a single thread.
The GIL which is currently being removed from CPython?
Yeah, in newer versions
Ugh we already have BATMAN and ROBIN as meshnet. Can't you go with... sea man or some other thing that's not taken?
one word VENGEANCE