wp-graphql / wpgraphql-acf

Re-architecture of WPGraphQL for ACF
GNU General Public License v3.0
73 stars 10 forks source link

Slower Query Resolution with GraphQL Analyzer vs Previous Plugin #218

Open rodrigo-arias opened 1 month ago

rodrigo-arias commented 1 month ago

Description

After migrating to the new plugin, I noticed that query resolution was slower than before. In a minimal reproduction scenario, the query time increased from 240 ms to 400 ms. However, in more complex scenarios involving dozens of fields and larger datasets, the uncached request times have increased from 1.2 seconds to 3.7 seconds, which is quite significant, and started overloading the server.

Steps to reproduce

Check the resolution time in the GraphiQL network tab.

WPGraphQL for Advanced Custom Fields (old):

query GET_TEST {
  post(id: "/test", idType: SLUG) {
    title
    personRelationship {
      toPerson {
        ... on Person {
          id
          title
        }
      }
    }
    pageRelationship {
      toPage {
        ... on Page {
          id
          title
        }
      }
    }
  }
}

WPGraphQL for ACF (new):

query GET_TEST {
  post(id: "/test", idType: SLUG) {
    title
    personRelationship {
      toPerson {
        nodes {
          ... on Person {
            id
            title
          }
        }
      }
    }
    pageRelationship {
      toPage {
        nodes {
          ... on Page {
            id
            title
          }
        }
      }
    }
  }
}

PHP or JSON export of the ACF Field Group(s)

acf-export-2024-06-19.json.zip

Additional context

CleanShot 2024-06-18 at 20 49 07 vs. CleanShot 2024-06-18 at 20 50 07

WPGraphQL Version

1.27.0

WPGraphQL For ACF Version

2.2.0

ACF (Advanced Custom Fields) Version. Free or Pro?

6.3.1.2 Pro

WordPress Version

6.5.4

PHP Version

8.2

Additional enviornment details

GraphQL Type Tracking enabled

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

Please confirm that you have disabled ALL plugins except for WPGraphQL, WPGraphQL For ACF, ACF, etc.

rodrigo-arias commented 1 month ago

After further testing, this issue appears to be related to GraphQL Type Tracking. When this option is disabled, the difference in performance is marginal. However, when enabled, the headers significantly slow down the queries in the new version of the plugin. You can see the difference even if no related items are returned.

WPGraphQL for Advanced Custom Fields 0.6.1

CleanShot 2024-06-19 at 21 49 12

https://github.com/wp-graphql/wpgraphql-acf/assets/11416255/1292a4ec-17af-47c0-bd27-93ea5231da5d

WPGraphQL for ACF 2.3.0

CleanShot 2024-06-19 at 21 48 51

https://github.com/wp-graphql/wpgraphql-acf/assets/11416255/fb0c2be9-c035-479c-926e-f90cf14ce85f

josephfusco commented 3 weeks ago

Hey @rodrigo-arias thanks for reporting this and for the thorough issue. This looks good we will try to follow your steps to reproduce and come up with next steps. 🙌🏼

rodrigo-arias commented 3 weeks ago

Thanks @josephfusco, if I can help with anything just let me know.

jasonbahl commented 3 weeks ago

@rodrigo-arias Thanks for the detailed issue.

I've created an environment with the ACF Field Group export that you have provided and have successfully reproduced, noticing a significant increase when using WPGraphQL v2.3.0 + GRAPHQL_DEBUG + X-GraphQL-Key Tracking enabled.

I'm not sure yet what the culprit is or but the fact that I can reproduce is promising in looking for a solution.

I expect there to be some overhead when using WPGraphQL for ACF, but not this much!

Thanks again for reporting!

WPGraphQL for Acf v0.6.1

Query, modified for v0.6.1 (toPerson and toPage fields are not connections)

query GET_TEST {
  post(id: "/test", idType: SLUG) {
    title
    personRelationship {
      toPerson {
        __typename
        ... on Post {
          id
          title
        }
      }
    }
    pageRelationship {
      toPage {
        ... on Page {
          id
          title
        }
      }
    }
  }
}

X-GraphQL-Key Tracking Disabled & WPGRAPHQL_DEBUG disabled:

X-GraphQL-Key Tracking enabled & WPGRAPHQL_DEBUG enabled:

(~50% increase)

WPGraphQL for ACF v2.3.0

Query, modified for v0.6.1 (toPerson and toPage fields ARE connections)

query GET_TEST {
  post(id: "/test", idType: SLUG) {
    title
    personRelationship {
      toPerson {
        nodes {
          __typename
          ... on Person {
            id
            title
          }
        }
      }
    }
    pageRelationship {
      toPage {
        nodes {
          ... on Page {
            id
            title
          }
        }
      }
    }
  }
}

X-GraphQL-Key Tracking Disabled & WPGRAPHQL_DEBUG disabled:

X-GraphQL-Key Tracking enabled & WPGRAPHQL_DEBUG enabled:

(>500% increase 😱)

rodrigo-arias commented 3 weeks ago

@jasonbahl It's good that you're seeing the same thing. Thanks for checking!

jasonbahl commented 3 weeks ago

However, in more complex scenarios involving dozens of fields and larger datasets, the uncached request times have increased from 1.2 seconds to 3.7 seconds

@rodrigo-arias can you share more information on this scenario? The more information I have to reproduce scenarios, the better understanding I can get around what issue(s) are occurring and how to address them.

jasonbahl commented 1 week ago

This PR might have a positive impact on this issue: https://github.com/wp-graphql/wp-graphql/pull/3172

rodrigo-arias commented 1 week ago

@jasonbahl Sorry for the late answer. This might be too much context, but you can determine what is relevant.

The websites I work on rely heavily on bidirectional relationship fields (using Post 2 Post for ACF and registered via PHP). Depending on the post type, queries can include dozens of these related posts, as well as their titles, categories, tags, other taxonomies, and custom fields.

A typical query structure includes:

We use WPGraphQL, WPGraphQL for ACF, WPGraphQL Tax Query, WPGraphQL Yoast SEO, WPGraphQL Gutenberg (planned to migrate to WPGraphQL Content Blocks), and WPGraphQL for Gravity Forms.

For caching, we use WPGraphQL Smart Cache and have Object Cache enabled. We retrieve the data using Apollo Client with APQ (GET requests) and InMemoryCache.

I have tried splitting the queries into two parts: one for common data and one for post data, hoping the cache would quickly resolve the first. Since it is not possible to use apollo-link-batch with AQP, I tried parallel queries with Promise.all(). However, a single larger query proved to be more efficient.

At the moment, I don't see a way to reduce the amount of data required or obtain it more optimally.

That said, the videos I shared did not include WPGraphQL Tax Query, WPGraphQL Yoast SEO, WPGraphQL Gutenberg, WPGraphQL for Gravity Forms, Apollo Client, or any frontend configuration, as they were made directly from GraphiQL. Post content was not included, and related posts were not returned because they were not assigned.

Let me know if any additional details would be helpful.