-
Notifications
You must be signed in to change notification settings - Fork 769
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
Support for Async Django #1394
base: main
Are you sure you want to change the base?
Support for Async Django #1394
Conversation
Progress update: All the fields resolvers are supporting both being executed in the async context and wrapping django sync code into a sync context. I've made the assumption that any resolving of Currently people switching to using the async view will need to wrap all their top level resolvers (those that are directly on the Next steps are to run through all the test files and adding the helper. It would great if people could test this either on their production projects (speciically when running under ASGI), as 'm interested in how swapping in/out of the sync context affects the performance of the execution. |
This is great news! Would discuss with my team to try this on production once its ready! |
Migrating to v3 version, without making sure dataloaders and everything works, so that people need to implement new libraries (check @superlevure comments above) |
@alexandrubese so what's the way? |
@dima-kov Which might not be ideal because you’re basically just adding “legacy code” that you will need to update once they will make v3 work (although it’s been almost a year this is discussed, I don’t know when this will work and they will fix dataloaders) I don’t jnderstand the intricacies of the v3 update, maybe they had to do it, that’s why it was maybe forced ? Or use a different library PS: I don’t know why the Django team didn’t work to add proper GraphQL support. Spring, .Net MVC and many other “web frameworks” did it. |
Regarding the comment from @superlevure:
We are almost there; the only remaining tasks are performance benchmarks and documentation updates. This implies that most of the work is already done, and only a few percentages are left. @jaw9c, it seems you might be short on time for this. I'm willing to contribute efforts at this point. @superlevure, to be transparent, I haven't conducted performance testing before, but I'm attempting it now. Any suggestions on how to approach this appropriately would be highly appreciated. |
Data loaders that exist are not fully compatible with new versions of graphene and graphene-django. DjangoConnectionField doesn't seem to handle loaders correctly and instead return errors like: "Cannot return null for non-nullable field EmailNodeConnection.edges." So for now, data loaders will be disabled for this field type. Use graphql-sync-dataloaders to make other types of fields work with data loaders. Some GitHub issues for reference: - graphql-python/graphene-django#1394 - graphql-python/graphene-django#1263 - graphql-python/graphene-django#1425 Refs: HP-2082
Benchmarks: Details are here: https://github.com/dima-kov/django-graphene-benchmarks?tab=readme-ov-file#tldr Async:
vs Sync
@superlevure are we fine now? What should be next steps to make this public? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥
@dima-kov shouldn't you run sync benchmark with 10 workers instead of 4? I know that measuring sync vs async is hard but with 10 workers we would have consistent number of requests that are handled in the same time by the server so we should get actual comparison. I guess we should get similar results which is fine as the biggest benefit of using async is less resources used. |
hmm, that would eats lots of memory.
I'm running on 4 cores machine, so trying gunicorn with 9 workers I've got only slightly better result:
and memory usage was 9 processes ~80mb each = 720. The bottleneck here might be sqlite3 database. vs async:
and mem usage was 1 process 60mb. |
Sqlite docs says that concurrent writes are locked, but reads should be fine so I think it's not a problem with sqlite itself. Maybe it's because of the differences in sync and async resolvers? In async you're fetching related |
oh, shame on me. so here is fixed version comparison: Comparison
|
Now, it can be asserted that the releasing of the Async version will result in a twofold acceleration of I/O endpoints. Moreover, take a look on this much fair (same resources) comparison:
We encounter a tradeoff of x5 with identical resource utilization, excluding threads! |
Guys, we really need this (having async resolvers). Please tell us how can we help to make it public., I do not want to start using it unsure this is merged in main. Or at least let us know your are going to release this, but we are missing: 1,2,3... |
Thanks for the benchmarks, I'll review the PR again tomorrow. Note that I don't have merge rights on this repo, we'll need a review from one of @firaskafri, @sjdemartini, @kiendang (or others) |
@superlevure i think it is good to go as soon as we clarify the docs |
@dima-kov I had a look at your benchmarks and I have few remarks. First, it looks like you're comparing the Second, I noticed the I took the liberty of pushing a PR to your repo that covers those point, as well as setting up a I obtain the following results:
Data tends to show a huge perf hit for the
I suspect the I'll continue to play with the PR a bit tonight to make sure there's nothing wrong with my setup, but I'm curious if others can reproduce similar results. |
@superlevure thank you for looking into it! I missed that part |
regarding the results you've got: hmm, thats really strange. Both sync and async (100 requests concurrently and 1k requests in total) showed me +- 20s. 100+s is smth unbelievable for me. I'm playing with main version now.
|
Django currently doesn't support persistent connections for ASGI https://code.djangoproject.com/ticket/33497 |
Thank you for all your work! How can we help to get it merged? |
https://docs.djangoproject.com/en/5.1/releases/5.1/#postgresql-connection-pools django 5.1 will support connection pool and this might be an opportunity to merge the PR |
I was getting an error that the view is not async on the latest Django release Based on this, there must be an async method or the property returns false. As a quick fix, I pushed this classproperty to be true: Feel free to add that in. |
Apologies for the radio silence on this thread. Appreciate the feedback and efforts from everyone on this PR - in particular the benchmarking. A fair few months ago, we rolled this into production at my work, utilising the new I think this is safe to merge, but with an experimental warning for those willing to test and use the I've been carefully watching the movements by the Django team on making the ORM fully async, this PR is the latest, which is really encouraging! |
Looks like Django 5.1 got released! |
Are there plans to publish a tagged release? Happy to support if anything is missing. |
@jaw9c, do you think it's safe to merge even though my benchmarks showed this PR degrades performance for |
any luck with this? |
Feedback requested.
This PR adds support for Django async views. The general strategy follows the same principal as the base graphene library when supporting async. It implements the following things:
sync_to_async
The current progress is as followed:
Other thoughts:
sync_to_async
if they are performing ORM ops. It would be nice to detect this error and throw a warning on existing codebases.