graphql-shield: Performance degradation after applying graphql-shield

Bug report

  • I have checked other issues to make sure this is not a duplicate.

Describe the bug

Querying multiple fields for hundreds of rows becomes noticeably slower after applying graphql-shield middleware.

To Reproduce

I’ve created repository reproducing this issue: https://github.com/lynxtaa/graphql-shield-performance

  • Without graphlql-shield it takes 30-40ms to query all users.
  • With graphql-shield it takes ~260ms.

Notice that I’m not applying any rules for type User.

Is there a way to improve performance for large queries?

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 19 (10 by maintainers)

Most upvoted comments

@maticzav @lynxtaa I tried to do a bit more experimenting with profiling and looking at the garbage collection patterns. I’m no expert in either of these topics but I’m hoping what I found helps. I added a repo here to do the testing.

I setup a GraphQL server running on Express with a basic GraphQL schema that returns a list of Movies with 8 attributes. For the tests I randomly generated 100 movies to be returned in the GQL query. I used a resolver that pauses by 10s then returns (my attempt at poor man’s request queueing).

I used vegeta to do some load testing. When I tried doing 350req/s for 1m I noticed that when Shield was applied, there was twice as much garbage collection as when Shield middleware wasn’t there. I showed the results in the README of the project. Also, it would run out of memory ever so often when Shield was applied.

Finally, I used the v8-profiler-next to profile the system under load. I looked at the profiles in Chrome’s Javascript Profiler but not too much jumped out at me.

This profile shows running 350req/s with the 10s. Then I changed the resolver to return after 3s and recorded the results with Shield and without Shield. One caveat is that I had to stop the load testing early for Shield so that the NodeJS process didn’t quit on me. I needed to save the profile.

From the little I gleaned from the profiles, it confirms that the garbage collection takes longer. Compare with Shield… image

To without Shield… image

Hope this helps!

@maticzav I think it has something to do with typescript compilation of async functions. After some experimenting I’ve compiled graphql-shield with target: ESNext in tsconfig.json and the performance is much better: it takes 108ms on first call, then 59ms on second call.

Can you consider dropping Node 6 support and start compiling to es2017?

Thank you both for such profound insights on the performance. I am away for a vacation and will return on Tuesday.