-
Notifications
You must be signed in to change notification settings - Fork 672
Lots of events fired for a simple GraphQL query #6639
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
Comments
After further investigation I honestly think it was the DB instance it ran on as it runs well on a new one, so I think it's safe to say you can disregard my comment completely 😅 |
@Wiejeben Events themselves shouldn’t be a problem. And many of them will only fire if Dev Mode is enabled or there is an active event listener on them. If you send your Composer files and a database backup over to [email protected], plus an example GraphQL query, we can try profiling it and see if there are any opportunities to speed things up in your case. @Marcuzz Sounds unrelated, please post a new issue, or maybe just write into [email protected] as this will likely be something environmental. (The SQL query you posted looks like a typical entry query to me.) |
Send! |
I had to create a few more sections and fields which drastically increased the amount of events. Even sending the So I did some digging myself. Culprit is mainly Is there any way to perhaps make generating the GraphQL query definitions be cached globally and refreshed at every configuration change instead of every query/variable change? I'm really curious to finding a solution to this! Note: Turning |
Having xDebug enabled significantly increases operation time for everything - have you tried turning it off to see what the timings are? |
@andris-sevcenko Turning everything off indeed improves the performance. However Executing the However lets say my blog index (with 15 articles) takes about 2.1 seconds: query blogIndex($uri: String) {
...seomatic
entry(section: "blogIndex") {
... on blogIndex_blogIndex_Entry {
title
subTitle
}
}
articles: entries(section: "blog") {
...blogCard
}
articlesCount: entryCount(section: "blog")
}
fragment seomatic on Query {
seomatic(uri: $uri) {
... on SeomaticInterface {
metaTitleContainer
metaTagContainer
metaLinkContainer
metaJsonLdContainer
}
}
}
fragment cardImageUrls on AssetInterface {
urlLarge: url @transform(handle: "cardLarge", immediately: false)
urlMedium: url @transform(handle: "cardMedium", immediately: false)
urlSmall: url @transform(handle: "cardSmall", immediately: false)
urlXsmall: url @transform(handle: "cardXsmall", immediately: false)
}
fragment blogCard on blog_blog_Entry {
title
slug
dateCreated @formatDateTime(format: "d M Y")
blogAuthor
blogCategory(limit: 1) {
title
}
pageImages(limit: 1) {
title
focalPoint
...cardImageUrls
}
} Same goes for the blog detail, about 2.1 seconds: query blogShow($uri: String, $slug: [String]) {
...seomatic
entry(section: "blog", slug: $slug) {
... on blog_blog_Entry {
title
slug
dateCreated @formatDateTime(format: "d M Y")
blogAuthor
blogCategory(limit: 1) {
title
}
pageImages {
title
focalPoint
...pageImageUrls
}
pageContentMatrix {
...pageContentMatrix
}
}
}
articles: entries(section: "blog", limit: 4) {
...blogCard
}
}
fragment seomatic on Query {
seomatic(uri: $uri) {
... on SeomaticInterface {
metaTitleContainer
metaTagContainer
metaLinkContainer
metaJsonLdContainer
}
}
}
fragment pageImageUrls on AssetInterface {
urlLarge: url @transform(handle: "pageImageLarge", immediately: false)
urlSmall: url @transform(handle: "pageImageSmall", immediately: false)
}
fragment linkIt on linkField_Link {
url
type
text
target
}
fragment contentImageUrls on AssetInterface {
urlLarge: url @transform(handle: "contentImageLarge", immediately: false)
urlSmall: url @transform(handle: "contentImageSmall", immediately: false)
}
fragment pageContentMatrix on pageContentMatrix_MatrixField {
... on MatrixBlockInterface {
id
typeHandle
}
... on pageContentMatrix_text_BlockType {
blockContent
}
... on pageContentMatrix_quote_BlockType {
blockContent
blockSubTitle
}
... on pageContentMatrix_button_BlockType {
blockPrimary {
...linkIt
}
blockSecondaryPrefix
blockSecondary {
...linkIt
}
}
... on pageContentMatrix_image_BlockType {
blockSubTitle
image: blockContent {
title
id
...contentImageUrls
}
}
}
fragment cardImageUrls on AssetInterface {
urlLarge: url @transform(handle: "cardLarge", immediately: false)
urlMedium: url @transform(handle: "cardMedium", immediately: false)
urlSmall: url @transform(handle: "cardSmall", immediately: false)
urlXsmall: url @transform(handle: "cardXsmall", immediately: false)
}
fragment blogCard on blog_blog_Entry {
title
slug
dateCreated @formatDateTime(format: "d M Y")
blogAuthor
blogCategory(limit: 1) {
title
}
pageImages(limit: 1) {
title
focalPoint
...cardImageUrls
}
} |
Do you have |
Yes it is enabled. Executing the same query a second time takes less than 0.2 second which is great. However this is a very dynamic website so a lot of content will be updated multiple times per hour, invalidating the cache. |
Discussed this with @andris-sevcenko over Discord. GraphQL does run faster on his machine. Caching/serializing Will personally be looking into cache warming since the cached response rates are beyond excellent! |
Just deployed to our new server setup. Even with the X-Debug tool enabled it's generating uncached GraphQL responses in 0.2 seconds. I guess my local setup wasn't so fast after all... |
Glad to hear that, @Wiejeben! That’s actually pretty impressive if Xdebug is enabled. |
@brandonkelly - So this is interesting - we have a headless site paired with a static site generator, and whenever the site regenerates we are seeing the server spend almost all of its time rebuilding the schema via We have our rebuild pretty well-optimized (GQL caching as well as GQL batching, on pages with multiple calls), but digging into the API GQL controller I can see that even with GQL caching, it does quite a bit of work pulling the schema definition on every request. Would it be possible for the schema to be cached once the query has been validated? Seems like there is a lot of time being spent here when it probably doesn't have to. |
@mildlygeeky just opened a new issue for this to keep track. |
Uh oh!
There was an error while loading. Please reload this page.
Description
Today I noticed my GraphQL queries taking ages (minimum of 1 second). Sending the same query again only takes about 100 ms because of caching. Changing the query or variables would take 1+ second again.
Did some digging in the Yii Debugger and noticed 3671 events were fired, mostly
defineBehaviors, craft\events\DefineBehaviorsEvent, craft\models\EntryType
andinit yii\base\Event craft\models\EntryType
. However so far I have only created 15 entrytypes.With this I also noticed more MySQL queries than I would reasonably expect.
I compared this behaviour with a website in production. Running running 3.4.27 its also making makes 4271 events.
Hopefully some improvements can be made making GraphQL more lightweight! I'm not too sure what's happening underneath the hood but if I were to guess than it is probably rebuilding the entire GraphQL schema on every single new call? Just before the thousands of repeated events,
RegisterGqlTypesEvent
is triggered.Steps to reproduce
This MySQL query is being called 60 times total, with every layoutId was being called 3 times.
SELECT `fields`.`id`, `fields`.`dateCreated`, `fields`.`dateUpdated`, `fields`.`groupId`, `fields`.`name`, `fields`.`handle`, `fields`.`context`, `fields`.`instructions`, `fields`.`translationMethod`, `fields`.`translationKeyFormat`, `fields`.`type`, `fields`.`settings`, `fields`.`uid`, `fields`.`searchable`, `flf`.`layoutId`, `flf`.`tabId`, `flf`.`required`, `flf`.`sortOrder` FROM `fields` `fields` INNER JOIN `fieldlayoutfields` `flf` ON `flf`.`fieldId` = `fields`.`id` INNER JOIN `fieldlayouttabs` `flt` ON `flt`.`id` = `flf`.`tabId` WHERE `flf`.`layoutId`=24 ORDER BY `flt`.`sortOrder`, `flf`.`sortOrder
This MySQL query is being called 90 times:
SELECT `id`, `sectionId`, `fieldLayoutId`, `name`, `handle`, `sortOrder`, `hasTitleField`, `titleFormat`, `uid`, `titleTranslationMethod`, `titleTranslationKeyFormat` FROM `entrytypes` WHERE `dateDeleted` IS NULL
Additional info
No modules, a very much vanilla headless Craft setup.
The text was updated successfully, but these errors were encountered: