dragonfly/tools/json_benchmark.py

123 lines
3.7 KiB
Python
Raw Normal View History

#!/usr/bin/env python
import multiprocessing
import time
import redis
import sys
import argparse
from urllib.parse import urlparse
import os
from collections import defaultdict
import math
'''
Run JSON benchmark for 3 commands:
JSON.SET
JSON.GET
JSON.TYPE
We want to the overall time it takes
to save and access keys that contains
JSON values with this benchmark.
This also verify that the basic functionalities
for using JSON types work correctly
'''
def ping(r):
r.ping()
def jsonset(r, i):
key = "json-{}".format(i)
r.execute_command('JSON.SET', key, '.', '{"a":123456, "b": "hello", "nested": {"abc": "ffffff", "bfb": null}}')
def jsonget(r, i):
key = "json-{}".format(i)
r.execute_command('JSON.GET', key, '$.a', '$..abc')
def jsontype(r, i):
key = "json-{}".format(i)
r.execute_command('JSON.TYPE', key, '$.a')
def runWorker(ctx):
wpid = os.getpid()
print( '{} '.format(wpid))
rep = defaultdict(int)
r = redis.StrictRedis(host=ctx['host'], port=ctx['port'])
work = ctx['work']
if ctx['pipeline'] == 0:
total_count = int(ctx['count'])
for i in range(0, total_count):
s0 = time.time()
jsonset(r, i)
s1 = time.time() - s0
bin = int(math.floor(s1 * 1000)) + 1
rep[bin] += 1
for i in range(0, total_count):
s0 = time.time()
jsonget(r, i)
s1 = time.time() - s0
bin = int(math.floor(s1 * 1000)) + 1
rep[bin] += 1
for i in range(0, total_count):
s0 = time.time()
jsontype(r, i)
s1 = time.time() - s0
bin = int(math.floor(s1 * 1000)) + 1
rep[bin] += 1
else:
for i in range(0, ctx['count'], ctx['pipeline']):
p = r.pipeline()
s0 = time.time()
for j in range(0, ctx['pipeline']):
work(p)
p.execute()
s1 = time.time() - s0
bin = int(math.floor(s1 * 1000)) + 1
rep[bin] += ctx['pipeline']
return rep
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='ReJSON Benchmark', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-c', '--count', type=int, default=100000, help='total number of operations')
parser.add_argument('-p', '--pipeline', type=int, default=0, help='pipeline size')
parser.add_argument('-w', '--workers', type=int, default=8, help='number of worker processes')
parser.add_argument('-u', '--uri', type=str, default='redis://localhost:6379', help='Redis server URI')
args = parser.parse_args()
uri = urlparse(args.uri)
r = redis.Redis(host=uri.hostname, port=uri.port)
pool = multiprocessing.Pool(args.workers)
s0 = time.time()
ctx = {
'count': args.count / args.workers,
'pipeline': args.pipeline,
'host': uri.hostname,
'port': uri.port,
'work': jsonset,
}
print ('Starting workers: ')
p = multiprocessing.Pool(args.workers)
results = p.map(runWorker, (ctx, ) * args.workers)
print("")
sys.stdout.flush()
s1 = time.time() - s0
agg = defaultdict(int)
for res in results:
for k, v in res.items():
agg[k] += v
print()
count = args.count * 3
print (f'Count: {args.count}, Workers: {args.workers}, Pipeline: {args.pipeline}')
print (f'Using hireds: {redis.utils.HIREDIS_AVAILABLE}')
print (f'Runtime: {round(s1, 2):,} seconds')
print (f'Throughput: {round(count/s1, 2):,} requests per second')
for k, v in sorted(agg.items()):
perc = 100.0 * v / count
print (f'{perc:.4f}% <= {k:,} milliseconds')