37

Quiver – GraphQL on Steroids

 5 years ago
source link: https://www.tuicool.com/articles/hit/bEZnQbm
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
zMBRj2M.png!web

:chart_with_upwards_trend: If you are mostly interested on the benchmarks between different GraphQL servers (Python, JS, Scala, Go…) you can jump directly to the charts at the end :point_down:

I’ll be frank… I’ve been obsessed with GraphQL performance for the last few years. Aiming to improve it, I created Quiver.

Quiver is a GraphQL engine that focuses on making GraphQL as fast as possible by removing the overhead of the GraphQL runtime .

So, how is Quiver achieving a * blazing-fast speed when executing queries?

First, we need to analyze what happens when we run a GraphQL query.

Steps for executing a GraphQL query

Each time a GraphQL query is executed (e.g. graphql(schema, '{ hello }') ), the following happens:

  1. The query string { hello } is parsed into a GraphQL AST .
  2. The GraphQL AST is validated against the schema. This ensures that the query is not just valid, but correct according to the schema. For example, this step checks that the type fields requested are available in the schema.
  3. At runtime , the engine walks through the GraphQL AST and determines the fields requested from the query. An object containing the requested fields filled with data is returned.
  4. The GraphQL view serializes the resulting object into something a client can consume (e.g. JSON).

* I’m intentionally skipping the HTTP transport step for sending the results back to the client.

So, what can we do to speed up the queries?

Having analyzed the different steps, there are some strategies that will help us to optimize the execution speed:

  • Cache the GraphQL AST of a given query, so that we avoid parsing subsequent similar queries.
  • Only allow certain queries from a document store . This have two main implications: being able to control the queries that are executed against our schema, and therefore assume that queries are already validated so we don’t need to check them at runtime.
  • Minimize the runtime logic for the query. A simple approach could be to traverse the GraphQL fields for a specific selection into code, so we don’t need to do process this logic at runtime.
    The compilation strategy is something that template engines have been doing for years ( Jinja , Hero , …).

While Quiver focuses on the latter, it’s approach also removes the need of parsing and validating the AST at runtime for each query execution.

Quiver is to GraphQL what a compiled language (C, Go, …) is to an interpreted one (Python, Ruby, …).

By analyzing and compiling the query into code, we can achieve substantial speed improvements.

So, how does Quiver work?

Let’s say you want to execute the following Query:

query HelloWorld {
  hello
}

Quiver will compile it into something similar to (depending on the language):

def execute(root, variables=None, operation_name=None):
    if operation_name is None or operation_name == 'HelloWorld':
        selection_type = schema.get_type('Query')
        hello_resolver = selection_type.get_field('hello').resolver
        info = ResolveInfo(...)
        return {
            'hello': hello_resolver(root, info)
        }

Because this compilation step happens only once, executing the HelloWorld GraphQL query will be as fast as executing a normal function that returns an object in the language of your choice, while being fully complaint with GraphQL and with no changes required on your GraphQL schema server-side.

Running the HelloWorld query will take only 9us when using Quiver in Python. Yes… that’s 0.009ms

Show me numbers!

When creating a project like this is important to be able to measure it objectively.

With this in mind, and inspired by graphql-bench from Hasura I created gbench , an utility library to help measure the speed of different GraphQL servers.

gbench will automatically start the servers locally, warm them up (when necessary) and benchmark each server against all the queries we indicate in the config file.

Here is a summary of the response time (per server & query) comparing Graphene, Graphene+Quiver, Node, Sangria and Go.

MbIrIbZ.png!web
The response time for GraphQL queries across different languages, using 20 concurrent connections

You can also check it in the dedicated website: speed.graphql-quiver.com

Quiver is able to handle up to 100k GraphQL queries per second in a single instance

It was a pleasant surprise to discover that Quiver in Python not only speeds up GraphQL in Python by a factor of 5–10x but also outperforms any other GraphQL engine available (including JS, Scala and even Go) by a great margin.

Ready for trying Quiver?

I’m very happy to announce that Quiver is now available to anyone using GraphQL in Python, and will be available in other major languages (JS, Ruby, Go) very soon.

Signup in the Quiver website and follow the instructions there :)

https://graphql-quiver.com/signup/

Just one-line code change will be enough to use Quiver in your current GraphQL setup in Python :)

You want try Quiver in JS, Go or Ruby?

The speedups are in the factor of 3 to 5x. Please ping me if you or your company is interested!

Try Quiver and start enjoying *blazing-fast GraphQL queries!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK