GraphQL execution using a JIT compiler
OTHER License
GraphQL-JS is a very well written runtime implementation of the latest GraphQL spec. However, by compiling to JS, V8 is able to create optimized
code which yields much better performance. graphql-jit
leverages this behaviour of V8 optimization by compiling the queries into functions to significantly improve performance (See benchmarks below)
GraphQL-JS 16 on Node 16.13.0
$ yarn benchmark skip-json
Starting introspection
graphql-js x 1,941 ops/sec ±2.50% (225 runs sampled)
graphql-jit x 6,158 ops/sec ±2.38% (222 runs sampled)
Starting fewResolvers
graphql-js x 26,620 ops/sec ±2.41% (225 runs sampled)
graphql-jit x 339,223 ops/sec ±2.94% (215 runs sampled)
Starting manyResolvers
graphql-js x 16,415 ops/sec ±2.36% (220 runs sampled)
graphql-jit x 178,331 ops/sec ±2.73% (221 runs sampled)
Starting nestedArrays
graphql-js x 127 ops/sec ±1.43% (220 runs sampled)
graphql-jit x 1,316 ops/sec ±2.58% (219 runs sampled)
Done in 141.25s.
The goal is to support the June 2018 version of the GraphQL spec.
graphql-js
In order to achieve better performance, the graphql-jit
compiler introduces some limitations.
The primary limitation is that all computed properties must have a resolver and only these can return a Promise
.
More details here - GraphQL-JS.md
yarn add graphql-jit
For complete working examples, check the examples/ directory
const typeDefs = `
type Query {
hello: String
}
`;
const resolvers = {
Query: {
hello() {
return new Promise((resolve) => setTimeout(() => resolve("World!"), 200));
}
}
};
const { makeExecutableSchema } = require("@graphql-tools/schema");
const schema = makeExecutableSchema({ typeDefs, resolvers });
const query = `
{
hello
}
`;
const { parse } = require("graphql");
const document = parse(query);
const { compileQuery, isCompiledQuery } = require("graphql-jit");
const compiledQuery = compileQuery(schema, document);
// check if the compilation is successful
if (!isCompiledQuery(compiledQuery)) {
console.error(compiledQuery);
throw new Error("Error compiling query");
}
const executionResult = await compiledQuery.query(root, context, variables);
console.log(executionResult);
const result = await compiledQuery.subscribe(root, context, variables);
for await (const value of result) {
console.log(value);
}
Compiles the document
AST, using an optional operationName and compiler options.
schema
{GraphQLSchema} - graphql
schema object
document
{DocumentNode} - document query AST ,can be obtained by parse
from graphql
operationName
{string} - optional operation name in case the document contains multiple operations(queries/mutations/subscription).
compilerOptions
{Object} - Configurable options for the compiler
disableLeafSerialization
{boolean, default: false} - disables leaf node serializers. The serializers validate the content of the field at runtimecustomSerializers
{Object as Map, default: {}} - Replace serializer functions for specific types. Can be used as a safer alternativecustomJSONSerializer
{boolean, default: false} - Whether to produce also a JSON serializer function using fast-json-stringify
. The default stringifier function is JSON.stringify
the compiled function that can be called with a root value, a context and the required variables.
(available for GraphQL Subscription only) the compiled function that can be called with a root value, a context and the required variables to produce either an AsyncIterator (if successful) or an ExecutionResult (error).
the compiled function for producing a JSON string. It will be JSON.stringify
unless compilerOptions.customJSONSerializer
is true.
The value argument should be the return of the compiled GraphQL function.
MIT