Last active
February 5, 2020 13:55
-
-
Save jedie/581444e02e784ff7c2b9fb1e763759fa to your computer and use it in GitHub Desktop.
Benchmark graphql-core
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
related issues: