Skip to content

Instantly share code, notes, and snippets.

@smerritt
Created July 25, 2013 21:13
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 smerritt/6083828 to your computer and use it in GitHub Desktop.
Save smerritt/6083828 to your computer and use it in GitHub Desktop.
benchmarking various python json libraries
#!/usr/bin/env python2.7
# -*- coding: utf-8 -*-
#
# Benchmark the relative performance of stdlib's json, simplejson, ujson, and
# a wrapped simplejson that gives the same API as stdlib's json.
import benchmark
import hashlib
import json as stdjson
import simplejson
import ujson
from datetime import datetime
# dumped out of MemcacheRing.set(), so it's not just realistic, it's real
# data.
CONTAINER_INFO = {
'bytes': '0',
'cors': {'allow_origin': None,
'expose_headers': None,
'max_age': None},
'meta': {'bert': 'ernie',
'bucky': 'balls',
'holy': 'guacamole',
'pants': 'moderately okayish',
'bit my sister': 'm\xc3\xb8\xc3\xb8se', # møøse
'thing1': 'thing2'},
'object_count': '0',
'read_acl': None,
'status': 204,
'sync_key': None,
'versions': None,
'write_acl': None}
class simple2std(object):
@classmethod
def dumps(cls, obj, *a, **kw):
return simplejson.dumps(obj, *a, **kw)
@classmethod
def loads(cls, s, *a, **kw):
return cls.unicodeify(simplejson.loads(s, *a, **kw))
@classmethod
def unicodeify(cls, data):
if isinstance(data, dict):
keys = data.keys()
# JSON keys are always strings
for oldkey in keys:
if isinstance(oldkey, str):
newkey = oldkey.decode("utf-8")
data[newkey] = cls.unicodeify(data.pop(oldkey))
else:
data[oldkey] = cls.unicodeify(data[oldkey])
return data
elif isinstance(data, list):
return [unicodeify(elem) for elem in data]
elif isinstance(data, str):
return data.decode("utf-8")
else:
return data
# quick test to make sure that this little adapter actually works
adapted = repr(simple2std.loads(simple2std.dumps(CONTAINER_INFO)))
std = repr(stdjson.loads(stdjson.dumps(CONTAINER_INFO)))
if not adapted == std:
print "simplejson\n==========\n%s\n\njson\n====\n%s" % (adapted, std)
exit(1)
class BenchmarkContainerListingGeneration(benchmark.Benchmark):
each = 250
def setUp(self):
self.container_listing = [
("kitten-%5d.jpg" % i,
datetime.utcfromtimestamp(i).isoformat(),
"application/catphoto",
hashlib.md5(str(i)).hexdigest())
for i in xrange(10000)]
def test_simplejson(self):
simplejson.dumps(self.container_listing)
def test_stdjson(self):
stdjson.dumps(self.container_listing)
def test_ujson(self):
ujson.dumps(self.container_listing)
class BenchmarkSerializeForMemcache(benchmark.Benchmark):
each = 1000
def test_simplejson(self):
simplejson.dumps(CONTAINER_INFO)
def test_stdjson(self):
stdjson.dumps(CONTAINER_INFO)
def test_simple2std(self):
simple2std.dumps(CONTAINER_INFO)
def test_ujson(self):
ujson.dumps(CONTAINER_INFO)
class BenchmarkDeserializeForMemcache(benchmark.Benchmark):
each = 1000
def setUp(self):
self.serialized_container_info = stdjson.dumps(CONTAINER_INFO)
def test_simplejson(self):
simplejson.loads(self.serialized_container_info)
def test_stdjson(self):
stdjson.loads(self.serialized_container_info)
def test_simple2std(self):
simple2std.loads(self.serialized_container_info)
def test_ujson(self):
ujson.loads(self.serialized_container_info)
class BenchmarkInAndOutOfMemcache(benchmark.Benchmark):
"""
Simulate putting things into and pulling things out of memcache.
Takes a wild guess that things get read 10x as often as written.
"""
each = 500
reads_per_write = 10
def test_simplejson(self):
serialized = simplejson.dumps(CONTAINER_INFO)
for _ in xrange(self.reads_per_write):
simplejson.loads(serialized)
def test_stdjson(self):
serialized = stdjson.dumps(CONTAINER_INFO)
for _ in xrange(self.reads_per_write):
stdjson.loads(serialized)
def test_simple2std(self):
serialized = simple2std.dumps(CONTAINER_INFO)
for _ in xrange(self.reads_per_write):
simple2std.loads(serialized)
def test_ujson(self):
serialized = ujson.dumps(CONTAINER_INFO)
for _ in xrange(self.reads_per_write):
ujson.loads(serialized)
if __name__ == "__main__":
benchmark.main(format="markdown", numberFormat="%.6g")
Benchmark Report
================
BenchmarkContainerListingGeneration
-----------------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|------------|------------|--------------
ujson | 1 | 250 | 0.00985815 | 0.00121903 | 1.0
simplejson | 2 | 250 | 0.0267644 | 0.00293761 | 2.71495712931
stdjson | 3 | 250 | 0.147163 | 0.0164483 | 14.9280143391
BenchmarkDeserializeForMemcache
-------------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 1000 | 1.08066e-05 | 1.08338e-05 | 1.0
simplejson | 2 | 1000 | 2.11682e-05 | 2.39655e-05 | 1.9588315757
simple2std | 3 | 1000 | 0.000101923 | 5.23849e-05 | 9.43156245863
stdjson | 4 | 1000 | 0.000303297 | 0.000124987 | 28.0660327406
BenchmarkInAndOutOfMemcache
---------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 500 | 7.14092e-05 | 4.52036e-05 | 1.0
simplejson | 2 | 500 | 0.000183833 | 8.90496e-05 | 2.5743609605
simple2std | 3 | 500 | 0.00101074 | 0.000295679 | 14.1542175272
stdjson | 4 | 500 | 0.00310838 | 0.000662862 | 43.5290539277
BenchmarkSerializeForMemcache
-----------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 1000 | 1.18728e-05 | 3.22692e-05 | 1.0
simplejson | 2 | 1000 | 3.12355e-05 | 3.99828e-05 | 2.63084862846
simple2std | 3 | 1000 | 3.32651e-05 | 3.45954e-05 | 2.80179926905
stdjson | 4 | 1000 | 8.85217e-05 | 6.02435e-05 | 7.45586168119
Each of the above 10750 runs were run in random, non-consecutive order by
`benchmark` v0.1.5 (http://jspi.es/benchmark) with Python 2.6.8
Linux-3.2.0-48-generic-x86_64 on 2013-07-19 23:57:20.
Benchmark Report
================
BenchmarkContainerListingGeneration
-----------------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|------------|------------|--------------
ujson | 1 | 250 | 0.00959748 | 0.00115649 | 1.0
stdjson | 2 | 250 | 0.01506 | 0.00165911 | 1.56915759221
simplejson | 3 | 250 | 0.0225577 | 0.0022019 | 2.35037410238
BenchmarkDeserializeForMemcache
-------------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 1000 | 8.48603e-06 | 1.66303e-05 | 1.0
simplejson | 2 | 1000 | 1.58083e-05 | 2.97476e-05 | 1.86286629393
stdjson | 3 | 1000 | 2.80697e-05 | 2.92579e-05 | 3.30775714326
simple2std | 4 | 1000 | 7.62441e-05 | 4.86442e-05 | 8.98465990504
BenchmarkInAndOutOfMemcache
---------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 500 | 6.24366e-05 | 4.20786e-05 | 1.0
simplejson | 2 | 500 | 0.000141842 | 9.58023e-05 | 2.27178304401
stdjson | 3 | 500 | 0.000267761 | 0.000158129 | 4.28852366369
simple2std | 4 | 500 | 0.000787121 | 0.000328854 | 12.6067329062
BenchmarkSerializeForMemcache
-----------------------------
name | rank | runs | mean | sd | timesBaseline
-----------|------|------|-------------|-------------|--------------
ujson | 1 | 1000 | 7.50256e-06 | 3.83522e-06 | 1.0
stdjson | 2 | 1000 | 1.72763e-05 | 3.05832e-05 | 2.30272022372
simplejson | 3 | 1000 | 2.06041e-05 | 1.33349e-05 | 2.74628193721
simple2std | 4 | 1000 | 2.16737e-05 | 1.13323e-05 | 2.88883945596
Each of the above 10750 runs were run in random, non-consecutive order by
`benchmark` v0.1.5 (http://jspi.es/benchmark) with Python 2.7.3
Linux-3.2.0-48-generic-x86_64 on 2013-07-19 23:53:08.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment