-
Notifications
You must be signed in to change notification settings - Fork 510
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
StrawberryIntegration slows down query performance dramatically #3670
Comments
Hey @pcraciunoiu, thanks for reporting. I'm thinking this might be due to the SDK in general having a lot of room for improvement in the async department. Might be the transport blocking. (There are plans for a fully async transport/SDK, but this will take some time.) Couple things to check:
|
It doesn't make a difference if the
I did try with I'll attach it in case it helps. If you have recommendations for other profiling tools that might do better, I'd like to learn about them. |
@pcraciunoiu Interesting, I also did not see anything in the profile you attached, although I am not really sure how pyinstrument works (sampling or deterministic). I think @sentrivana was suggesting that you could try using Sentry's built-in profiler. You can enable the profiler by setting Then, you can view the generated profiles directly in Sentry linked to the corresponding transaction. |
@szokeasaurusrex for the profiling I sent, I do not have sentry set up yet as it's a new project. I do have another project that was running the strawberry integration until late last week, when I found this issue and disabled it. I confirmed on that project too, that it was adding on 150ms or more to GraphQL requests as I tested locally. I have some profiling from last week before I disabled this integration, but it's a private repository and I'm not comfortable including links or details here. If you want to, I can share a sentry link privately via email or otherwise, and/or you can let me know what you need to look into this further. |
@pcraciunoiu Happy to look at the Sentry link -- you can send it to I will try to repro this today. Also want to compare the performance with a sync Django/Strawberry app. (My money is still on this being a general problem with the SDK blocking.) Will report back. |
It does not seem to make a difference from my quick tests |
The profile in Sentry looks thoroughly uneventful, but the pyinstrument profile you attached is interesting. Seems like there's a lot of time spent waiting on threading locks/conditions. Don't know if that's what's causing the slowness but we can verify that. Would you be able to get us a pyinstrument profile like the one above for the query:
We could then see what stands out. Feel free to attach here or send them to me via email. |
@sentrivana I finally got around to this and emailed you those files. It is definitely slowest with the strawberry integration async. |
Thanks @pcraciunoiu, got the files and will take a look in the next couple of days. |
@pcraciunoiu So I dug a bit deeper into this. Long story short, we're using a custom Strawberry extension in our integration. The only difference between the sync and async version of the extension is the To verify, I made a sample Django app with import strawberry
import strawberry_django
from strawberry_django.optimizer import DjangoOptimizerExtension
from strawberry.extensions import SchemaExtension
from inspect import isawaitable
from .types import Fruit
class MyExtension(SchemaExtension):
# # Uncomment this and comment out the async version to switch
# def resolve(self, _next, root, info, *args, **kwargs):
# return _next(root, info, *args, **kwargs)
async def resolve(self, _next, root, info, *args, **kwargs):
result = _next(root, info, *args, **kwargs)
if isawaitable(result):
result = await result
return result
@strawberry.type
class Query:
fruits: list[Fruit] = strawberry_django.field()
schema = strawberry.Schema(
query=Query,
extensions=[
DjangoOptimizerExtension, # not required, but highly recommended
MyExtension,
],
) I get the same performance difference using the sync vs. async version of Now the question for me would be if this is expected or if we're doing something wrong. Maybe @patrick91 could weigh in on this. TL;DR: The async version of the extension in the example above considerably slows down the endpoint, is this expected? The sync version adds almost no overhead in comparison. The app is just the example app from https://github.com/strawberry-graphql/strawberry-django?tab=readme-ov-file#basic-usage, using |
If I recall correct is awaitable is a slow check, also we are calling resolver for all fields, also the ones that might not need it @sentrivana maybe you can add this check for the basic fields? https://github.com/strawberry-graphql/strawberry/blob/main/strawberry/extensions/tracing/utils.py#L12-L20 |
@patrick91 Thanks for getting back to me. So do I understand this right, adding Or did you mean something different by adding it for the basic fields? I assume you mean in the app? |
@patrick91 you're correct with that you can skip the tracing entirely: I think on our side we could find ways to skip the |
I'll keep this open for us to investigate whether we can get rid of the |
I've also done some benchmarks on the EDIT: maybe PR had an error which I only just noticed |
How do you use Sentry?
Sentry Saas (sentry.io)
Version
2.17.0
Steps to Reproduce
Expected Result
Not much performance difference with or without
StrawberryIntegration
Actual Result
With
StrawberryIntegration
, this took 3-4x longer. In my case, about 800ms. Without it, I got the results back in 200-250ms.The text was updated successfully, but these errors were encountered: