Skip to content
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

Performance issue when loading text domains. #2721

Open
2 tasks done
creative-andrew opened this issue Feb 11, 2023 · 5 comments
Open
2 tasks done

Performance issue when loading text domains. #2721

creative-andrew opened this issue Feb 11, 2023 · 5 comments
Labels
Component: Query scope: i18n Affects usage in non-English language contexts. Type: Enhancement New feature or request

Comments

@creative-andrew
Copy link

creative-andrew commented Feb 11, 2023

Description

Every single GraphQL field has a semantic description, which looks like is getting translated on every single query even though they don't really need to be.

This is creating massive calls to the __() and load_textdomain() functions.

Additionally, the whole schema seems to be created and queried during each request, generating a massive object that is impossible to cache.

Steps to reproduce

  1. This should be tested in a similar way to this previously reported issue, namely by adding 30 CPT and terms.
  2. Perform some queries in English as the default language. Make sure your query includes a fair number of nodes and fields.
  3. Change to a different language and perform the same query.

Blocking wp-graphl text domain on demand.

If you prevent loading the $mofile for the wp-graphql text domain you would notice the speed bump. As a quick solution, developers can add this to a mu-plugin checking if the request is a WPGraphQL request. This solution should be removed once we have found a better approach.

// Adjust endpoint as needed.
$is_graphql = strpos($_SERVER['REQUEST_URI'], '/graphql') !== FALSE;
if ($is_graphql) {
  add_filter('override_load_textdomain',
    function ($override, $domain, $mofile) {
      return $domain === 'wp-graphql';
    }, 10, 3);
}

A testing branch has been created by another collaborator with the same issue: #1873 (comment) @idflood

image

image

Additional context

No response

WPGraphQL Version

1.13.8

WordPress Version

6.1.1

PHP Version

8.0.27

Please confirm that you have searched existing issues in the repo.

  • Yes

Please confirm that you have disabled ALL plugins except for WPGraphQL.

  • Yes
@jasonbahl
Copy link
Collaborator

I think we might be able to defer descriptions to be a callback and only execute them when actually called. . .like in introspection queries, for example. 🤔

@jasonbahl
Copy link
Collaborator

Additionally, the whole schema seems to be created and queried during each request, generating a massive object that is impossible to cache.

@creative-andrew I don't believe this is the case.

Let's take a look:

WordPress, no plugins

If we setup a fresh WordPress install (I'm using localwp to do it) and visit the /graphql endpoint WordPress will do it's thing and ultimately return a 404 (because WPGraphQL is not active)

But we can use this as our baseline of WordPress execution.

We can see that the "apply_filters" gets called 8,246 times

CleanShot 2023-02-14 at 17 16 12

And then we can dig in and see that "translate" calls it 1,954 times.

CleanShot 2023-02-14 at 17 18 04

If we visit the /wp-json/wp/v2/posts endpoint, we will see similar information.

"apply_filters" is called 8,887 times for this REST endpoint, and "translate" is called 4,110 times.

CleanShot 2023-02-14 at 17 19 29

If we visit the /wp-json/wp/v2 endpoint, we see the following:

"apply_filters" is called 17,108 times for this REST endpoint, and "translate" is called 8,218 times.

CleanShot 2023-02-14 at 17 34 23

WPGraphQL Active

If we activate WPGraphQL (v1.13.8) and visit the /graphl endpoint, this time we don't get the 404, instead we get the WPGraphQL error message saying we need to pass a query.

CleanShot 2023-02-14 at 17 21 32

If we look at the profiling for this request, we'll see the following:

CleanShot 2023-02-14 at 17 27 49

apply_filters called 13,401 times, 9,654 of them from translate.

If we go back to WPGraphQL v1.6.5 (shortly after the 1.6 release that targeted the "lazy loading" problem) we would see the following output:

apply_filters called 12,817 times, 9,306 of them from translate.

So yes, a there's an increase from some of the other endpoints, but definitely not the whole schema worth.

CleanShot 2023-02-14 at 17 27 40

If we go back to WPGraphQL v1.5.9, before the v1.6.0 release, we will see a significant change in the profiling, just by visiting the graphql endpoint and not even executing a query:

CleanShot 2023-02-14 at 17 27 11

Here we see apply_filters called 21,112 times, (increase from 12,817 in v1.6.5)
strtolower called 12,811 times (increase from 1,192 in v1.6.5)
WPGraphQL\Registry\TypeRegistry->format_key called 10,011 times, (increase from 898 in v1.6.5)
preg_match called 8,389 times (increase from 1,834 in v1.6.5)


I definitely think we have something to address here, but I don't think we have a regression to the 1.6 release. I don't see evidence suggesting that "the whole schema seems to be created and queried during each request".

This would be true for Introspection Queries, but I don't believe it's the case for every query.

Now, when queries are executed, the Types required to fulfill them will be loaded, so that would have an increase as well, but definitely not to the scope of loading the whole schema for each request.

So, the more complex queries get, the more types will be loaded, so I would expect an increase in Types being loaded for more complex queries.


I think we definitely should look into how we can register Types/Fields so that the descriptions are only executed/translated when needed (i.e. in Introspection Queries), but again, I don't believe there's evidence of a regression to 1.6 where the entire Schema is being loaded.

@justlevine
Copy link
Collaborator

(related: caching get_schema() thread on slack )

@justlevine justlevine added Type: Enhancement New feature or request Component: Query scope: i18n Affects usage in non-English language contexts. labels May 6, 2023
@creative-andrew
Copy link
Author

creative-andrew commented May 17, 2023

Related https://wp-graphql.slack.com/archives/C3NM1M291/p1684225596339229

Just for clarifying when I mentioned that the schema was called or registered on every request, I meant the schema inflation process.

@justlevine
Copy link
Collaborator

From core: https://make.wordpress.org/core/2023/07/24/i18n-performance-analysis/

Seems like adopting lazy-loading is the way to go, while still benefiting from any upstream improvements to the parser.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Query scope: i18n Affects usage in non-English language contexts. Type: Enhancement New feature or request
Projects
Status: 🆕 New
Development

No branches or pull requests

3 participants