Express-graphql: Performance improvement caching validation

Created on 26 Feb 2019  路  4Comments  路  Source: graphql/express-graphql

I'm currently using GraphQL to transform large documents and I've noticed a significant amount of time in validate. https://github.com/graphql/express-graphql/blob/master/src/index.js#L254

validate(schema, documentAST, validationRules);

The time spent on the first request:

parse: 21.042ms
hash: 3.727ms
validate: 965.500ms <
execute: 331.606ms

If I cache the result of validate. The time spent on the second request:

parse: 49.794ms
hash: 5.105ms
validate: 5.203ms <
execute: 336.634ms

As far as I can tell the schema is static, the query is the same with different arguments, and the validation rules are the same.

The change looks something like:

hash = hashFn(schema, documentAST, validationRules)

if (!cache[hash]) {
   cache[hash] = validate(schema, documentAST, validationRules);
}

const validationErrors = cache[hash];

As it's currently stateless, I'm trying to understand the trade-offs caching the result. I would appreciate any input from the contributors / maintainers. Basically, is this a terrible idea?

enhancement

Most helpful comment

Fixed in master.
@jamesmoriarty Thanks for PR 馃憤

All 4 comments

@jamesmoriarty GraphQL validate functionality was designed with a pretty similar case in mind:
https://facebook.github.io/graphql/June2018/#sec-Validation

Typically validation is performed in the context of a request immediately before execution, however a GraphQL service may execute a request without explicitly validating it if that exact same request is known to have been validated before. For example: the request may be validated during development, provided it does not later change, or a service may validate a request once and memoize the result to avoid validating the same request again in the future. Any client鈥恠ide or development鈥恡ime tool should report validation errors and not allow the formulation or execution of requests known to be invalid at that given point in time.

Moreover you can optimise it a little bit more by hashing query string before parsing it to AST.
AFAIK Facebook engineer went one step forward and hash queries during development so client sents only hash. Here is a talk with more details: https://youtu.be/G_zipR8Y8Ks

Thanks @IvanGoncharov. I really appreciate the response.

Is this a feature the maintainers would be interested in merging? If so is there any guidance on how the maintainers would like it implemented?

app.use('/graphql', graphqlHTTP({
  schema: MyGraphQLSchema,
  graphiql: true,
  validationCache: false <default> | <cache object e.g. {} or LRU>
}));

cc/ @wincent @zpao @kassens

Fixed in master.
@jamesmoriarty Thanks for PR 馃憤

@IvanGoncharov Is the proposal for validationCache accepted? I looking to do a similar kind of optimization for improving GraphQL performance

Was this page helpful?
0 / 5 - 0 ratings

Related issues

justinmchase picture justinmchase  路  4Comments

violet-day picture violet-day  路  3Comments

dhurlburtusa picture dhurlburtusa  路  4Comments

langpavel picture langpavel  路  5Comments

kaareal picture kaareal  路  3Comments