Skip to content

Instantly share code, notes, and snippets.

@jedie
Last active February 5, 2020 13:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jedie/581444e02e784ff7c2b9fb1e763759fa to your computer and use it in GitHub Desktop.
Save jedie/581444e02e784ff7c2b9fb1e763759fa to your computer and use it in GitHub Desktop.
Benchmark graphql-core
import cProfile
import pstats
import statistics
import time
import timeit
from collections import OrderedDict, namedtuple
import graphql
from graphql.graphql import execute_graphql
from graphql.type import (
GraphQLField,
GraphQLList,
GraphQLNonNull,
GraphQLObjectType,
GraphQLSchema,
GraphQLString,
)
EntryType = GraphQLObjectType(
"Entry",
fields=lambda: {
"id": GraphQLField(GraphQLNonNull(GraphQLString)),
"name": GraphQLField(GraphQLString),
},
)
Entry = namedtuple('Entry', 'id name')
entries = [Entry(id=f'id{i}', name=f'Entry Name {i}') for i in range(1000)]
def resolve_entry(context, info):
return entries
schema = GraphQLSchema(
query=GraphQLObjectType(
name='Query',
fields={
'entry': GraphQLField(
GraphQLList(EntryType),
resolver=resolve_entry,
),
}
)
)
def benchmark():
print('Benchmark')
print(f'graphql-core v{graphql.__version__}')
query = """{
entry {
id
name
}
}
"""
query = " ".join(line.strip() for line in query.splitlines())
statement = f"execute_graphql(schema, request_string='{ query }').data"
print(f'Use timeit statement: {statement}')
# verify test code:
result = eval(statement)
entries = result["entry"]
assert len(entries) == 1000, len(entries)
assert entries[0] == OrderedDict(
[('id', 'id0'), ('name', 'Entry Name 0')]), entries[0]
assert entries[999] == OrderedDict(
[('id', 'id999'), ('name', 'Entry Name 999')]), entries[999]
print()
print('_' * 100)
print('calculate timeit loop count, by execute one time:\n')
print('Run one timeit call...', end=' ', flush=True)
duration = timeit.timeit(
stmt=statement,
globals=globals(),
number=1,
)
print(f'takes: {duration*1000:.1f} ms')
print()
print('_' * 100)
max_time = 5 # how long in sec. should the timeit run?
print(f'timeit for ~{max_time:.0f}sec.:\n')
repeat = 5
number = int(max_time / repeat / duration)
print(
f'timeit... (use {repeat} * {number} loop, should take ca. {max_time:.0f} sec.)...',
end=' ',
flush=True
)
start_time = time.monotonic()
results = timeit.repeat(
stmt=statement,
globals=globals(),
repeat=repeat,
number=number,
)
print(f'takes: {time.monotonic()-start_time:.2f} sec.')
print(f'max...: {max(results)/number*1000:.2f} ms')
print(f'median: {statistics.median(results)/number*1000:.2f} ms')
print(f'min...: {min(results)/number*1000:.2f} ms')
print()
print('_' * 100)
print('run cProfile...\n')
pr = cProfile.Profile()
pr.enable()
eval(statement)
pr.disable()
pstats.Stats(pr).sort_stats('tottime', 'cumulative', 'calls').print_stats(20)
if __name__ == '__main__':
benchmark()
Benchmark
graphql-core v2.3.1
Use timeit statement: execute_graphql(schema, request_string='{ entry { id name } } ').data
____________________________________________________________________________________________________
calculate timeit loop count, by execute one time:
Run one timeit call... takes: 21.3 ms
____________________________________________________________________________________________________
timeit for ~5sec.:
timeit... (use 5 * 46 loop, should take ca. 5 sec.)... takes: 4.69 sec.
max...: 20.49 ms
median: 20.39 ms
min...: 20.20 ms
____________________________________________________________________________________________________
run cProfile...
139505 function calls (129474 primitive calls) in 0.043 seconds
Ordered by: internal time, cumulative time, call count
List reduced from 223 to 20 due to restriction <20>
ncalls tottime percall cumtime percall filename:lineno(function)
2001/1 0.005 0.000 0.042 0.042 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:317(resolve_field)
4001/1 0.003 0.000 0.041 0.041 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:500(complete_value)
32314/32308 0.003 0.000 0.003 0.000 {built-in method builtins.isinstance}
9006 0.003 0.000 0.014 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/promise/promise.py:804(is_thenable)
3005 0.002 0.000 0.006 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/abc.py:196(__subclasscheck__)
3001/1 0.002 0.000 0.041 0.041 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:463(complete_value_catching_error)
1001/1 0.002 0.000 0.043 0.043 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:230(execute_fields)
2001 0.002 0.000 0.004 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/utils.py:140(get_argument_values)
3002 0.001 0.000 0.003 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/promise/promise.py:825(is_future_like)
3005 0.001 0.000 0.007 0.000 /usr/lib/python3.6/typing.py:1145(__subclasscheck__)
3005 0.001 0.000 0.008 0.000 {built-in method builtins.issubclass}
6013 0.001 0.000 0.001 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/_weakrefset.py:70(__contains__)
2000 0.001 0.000 0.002 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/utils.py:351(default_resolve_fn)
1 0.001 0.001 0.041 0.041 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:578(complete_list_value)
6006 0.001 0.000 0.001 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/language/ast.py:260(__hash__)
1000 0.001 0.000 0.001 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/utils.py:158(get_sub_fields)
3005 0.001 0.000 0.001 0.000 /usr/lib/python3.6/typing.py:1033(_abc_negative_cache_version)
2000 0.001 0.000 0.002 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:616(complete_leaf_value)
2001 0.001 0.000 0.004 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/site-packages/graphql/execution/executor.py:443(resolve_or_error)
3002 0.001 0.000 0.001 0.000 /home/jens/.local/share/virtualenvs/foo-bar/lib/python3.6/weakref.py:431(__contains__)
@jedie
Copy link
Author

jedie commented Feb 5, 2020

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment