Performance

python-rapidjson tries to be as performant as possible while staying compatible with the json module.

Tables

The following tables show a comparison between this module and other libraries with different data sets. Last row (“overall”) is the total time taken by all the benchmarks.

Each number shows the factor between the time taken by each contender and python-rapidjson (in other words, they are normalized against a value of 1.0 for python-rapidjson): the lower the number, the speedier the contender.

In bold the winner.

Serialization

serialize dumps()[1] Encoder()[2] dumps(n)[3] Encoder(n)[4] ujson[5] simplejson[6] stdlib[7] yajl[8]
100 arrays dict 1.00 1.00 0.65 0.66 0.81 2.95 2.01 1.26
100 dicts array 1.00 1.00 0.71 0.67 0.79 3.82 1.94 1.16
256 Trues array 1.00 1.02 1.15 1.05 1.51 2.92 2.36 1.33
256 ascii array 1.00 1.00 1.02 1.01 0.50 1.14 0.87 0.91
256 doubles array 1.00 0.99 1.00 0.99 1.05 0.96 0.94 0.62
256 unicode array 1.00 0.87 0.87 0.88 0.55 0.76 0.73 0.55
apache.json 1.00 1.00 1.00 1.01 1.03 2.27 1.69 1.67
canada.json 1.00 1.00 0.99 0.99 0.16 1.39 1.04 0.70
complex object 1.00 1.01 0.88 0.88 0.61 1.87 1.45 1.17
composite object 1.00 0.90 0.66 0.62 0.71 2.08 1.51 1.64
ctm.json 1.00 1.00 0.68 0.69 1.09 3.45 1.96 1.41
github.json 1.00 1.01 0.96 0.96 0.86 1.63 1.36 1.49
instruments.json 1.00 1.00 0.72 0.72 0.88 1.83 1.58 1.47
mesh.json 1.00 1.00 0.91 0.90 0.22 1.11 0.99 0.61
truenull.json 1.00 1.01 1.03 1.00 2.20 2.19 1.91 1.35
tweet.json 1.00 1.02 1.00 0.94 0.96 2.17 1.64 1.33
twitter.json 1.00 1.00 0.94 0.94 0.94 1.47 1.32 1.32
overall 1.00 1.00 0.74 0.74 0.64 2.50 1.74 1.11

Deserialization

deserialize loads()[9] Decoder()[10] loads(n)[11] Decoder(n)[12] ujson simplejson stdlib yajl
100 arrays dict 1.00 1.00 0.90 0.89 0.97 1.25 0.98 1.14
100 dicts array 1.00 1.00 0.85 0.83 0.89 1.59 1.22 1.16
256 Trues array 1.00 0.99 1.12 1.01 1.12 1.84 1.59 1.92
256 ascii array 1.00 1.00 1.01 1.00 0.97 0.96 0.83 1.10
256 doubles array 1.00 1.00 0.23 0.22 0.56 1.09 1.06 0.47
256 unicode array 1.00 1.00 0.99 0.99 1.05 4.08 4.02 2.46
apache.json 1.00 0.99 1.01 1.00 1.00 0.94 0.96 1.15
canada.json 1.00 0.99 0.30 0.31 0.72 1.00 0.95 1.09
complex object 1.00 0.99 0.83 0.82 1.08 1.40 1.19 1.36
composite object 1.00 0.99 0.80 0.80 0.75 1.75 1.27 1.21
ctm.json 1.00 0.88 0.80 0.79 0.91 1.14 1.01 1.19
github.json 1.00 1.01 0.98 0.98 0.97 1.06 1.04 1.21
instruments.json 1.00 1.00 0.85 0.85 0.83 1.36 1.10 1.23
mesh.json 1.00 0.95 0.46 0.46 1.04 1.48 0.97 1.19
truenull.json 1.00 1.01 1.02 0.99 1.79 1.96 1.62 2.95
tweet.json 1.00 1.00 0.99 0.97 1.05 1.47 1.38 1.39
twitter.json 1.00 1.00 0.97 0.97 0.99 1.10 1.03 1.25
overall 1.00 0.99 0.84 0.84 0.95 1.24 0.98 1.14

ASCII vs UTF-8 Serialization

serialize rj ascii[13] rj utf8[14] uj ascii[15] uj utf8[16] sj ascii[17] sj utf8[18] json ascii[19] json utf8[20]
Long ASCII string 1.00 0.51 0.25 0.47 0.71 1.47 0.58 1.14
Long Unicode string 1.00 0.59 0.66 0.56 0.81 0.67 0.78 0.53
overall 1.00 0.57 0.54 0.53 0.78 0.91 0.72 0.71
[1]rapidjson.dumps()
[2]rapidjson.Encoder()
[3]rapidjson.dumps(number_mode=NM_NATIVE)
[4]rapidjson.Encoder(number_mode=NM_NATIVE)
[5]ujson 1.35
[6]simplejson 3.16.0
[7]Python 3.7.0 standard library json
[8]yajl 0.3.5
[9]rapidjson.loads()
[10]rapidjson.Decoder()
[11]rapidjson.loads(number_mode=NM_NATIVE)
[12]rapidjson.Decoder(number_mode=NM_NATIVE)
[13]rapidjson.dumps(ensure_ascii=True)
[14]rapidjson.dumps(ensure_ascii=False)
[15]ujson.dumps(ensure_ascii=True)
[16]ujson.dumps(ensure_ascii=False)
[17]simplejson.dumps(ensure_ascii=True)
[18]simplejson.dumps(ensure_ascii=False)
[19]stdlib json.dumps(ensure_ascii=True)
[20]stdlib json.dumps(ensure_ascii=False)

DIY

To run these tests yourself, clone the repo and run:

$ make benchmarks

to focus only on RapidJSON or:

$ make benchmarks-others

to get full comparison against other engines.

To reproduce the tables above, run:

$ make benchmark-tables

Compare different versions

pytest-benchmark implements an handy feature that allows you to weight the impact of a particular change. For example, you may start from a released version and execute:

$ make benchmarks PYTEST_OPTIONS=--benchmark-autosave

After applying whatever change to the code base, you can get a differential view by executing:

$ make benchmarks PYTEST_OPTIONS=--benchmark-compare=0001