Skip to content

Instantly share code, notes, and snippets.

@CTimmerman
Forked from marians/bench.py
Last active February 13, 2026 10:34
Show Gist options
  • Select an option

  • Save CTimmerman/1f328f02ac2740f4c90d to your computer and use it in GitHub Desktop.

Select an option

Save CTimmerman/1f328f02ac2740f4c90d to your computer and use it in GitHub Desktop.
Python serialization benchmark
"""
Python serialization benchmark
Based on https://gist.github.com/marians/f1314446b8bf4d34e782
2014-11-11 v1.0
2014-11-12 v1.1 Added compression and output size.
2026-02-12 v2.0 Added Fory and CBOR. Removed compression.
"""
import json, marshal, pickle, random
from dataclasses import dataclass
from hashlib import md5
from time import time
from typing import List, Dict
import uuid
#from zlib import compress, decompress # halves json float size (19 kB to 10 kB)
import cbor2, msgpack, pyfory, thrift
#import ujson # from http://www.lfd.uci.edu/~gohlke/pythonlibs/#ujson
# 2 to 3 times slower and up to 50% larger output than marshal.
# "pyfory provides a Python-native serialization mode that offers the same functionality as pickle/cloudpickle, but with significantly better performance, smaller data size, and enhanced security features." - https://fory.apache.org/docs/guide/python/native_mode
fory = pyfory.Fory(xlang=False, ref=False, strict=False)
@dataclass
class Person:
name: str
age: int
scores: List[int]
metadata: Dict[str, str]
data_size = 10
test_runs = 100_000
if __name__ == "__main__":
payload = {
"int": [random.randrange(0, 9999) for i in range(data_size)],
"float": [(random.randrange(0, 99) + random.random()) for i in range(data_size)],
"str": [md5(str(random.random()).encode('utf8')).hexdigest() for i in range(data_size)],
"dict": [dict((f"Key {i}", str(uuid.uuid4())) for i in range(data_size))],
"bytes": [[bytes([random.randint(0, 255) for j in range(200)]) for i in range(data_size)]],
"class": [Person(str(uuid.uuid4()), random.randint(0, 100), [random.randint(-100, 100) for j in range(10)], {"generic {i}": str(uuid.uuid4())}) for i in range(data_size)],
}
modules = [marshal, msgpack, pyfory, pickle, cbor2, json]
print(f"{test_runs:,d} times {data_size:,d} elements:")
for module in modules:
name = module.__name__
cumulative = time()
for payload_type in payload:
data = payload[payload_type]
if name == "pyfory":
dumps = fory.dumps
loads = fory.loads
elif name == "thrift":
dumps = thrift.save
loads = thrift.load
else:
dumps = module.dumps
loads = module.loads
start = time()
try:
if name in ['pickle', 'cPickle']:
for i in range(test_runs): serialized = dumps(data, protocol=-1) # -1 = highest available (2 in Python 2; 3 in Python 3.4 (2x speed))
else:
for i in range(test_runs): serialized = dumps(data)
w = time() - start
start = time()
for i in range(test_runs): unserialized = loads(serialized)
r = time() - start
except (TypeError, ValueError) as ex:
print(f"{module.__name__}\t{payload_type}\t{ex}")
continue
print(f"{module.__name__}\t{payload_type}\t{w:6.3f} sW {r:6.3f} sR {w+r:6.3f} sT {time() - cumulative:6.3f} sC {len(serialized):10,d} B")
print()
32-bit results in 64-bit Windows 7 Enterprise on Xeon W3540 @ 2.93 GHz 2.93 GHz (Dell Precision T3500):
C:\Python27\python.exe -u "serialization_benchmark.py"
1000 times 1000 elements:
json int W 0.125 R 0.156
pickle int W 2.808 R 1.139
cPickle int W 0.047 R 0.046
marshal int W 0.016 R 0.031
json float W 1.981 R 0.624
pickle float W 2.607 R 1.092
cPickle float W 0.063 R 0.062
marshal float W 0.047 R 0.031
json str W 0.172 R 0.437
pickle str W 5.149 R 2.309
cPickle str W 0.281 R 0.156
marshal str W 0.109 R 0.047
C:\pypy-1.6\pypy-c -u "serialization_benchmark.py"
1000 times 1000 elements:
json int W 0.515 R 0.452
pickle int W 0.546 R 0.219
cPickle int W 0.577 R 0.171
marshal int W 0.032 R 0.031
json float W 2.390 R 1.341
pickle float W 0.656 R 0.436
cPickle float W 0.593 R 0.406
marshal float W 0.327 R 0.203
json str W 1.141 R 1.186
pickle str W 0.702 R 0.546
cPickle str W 0.828 R 0.562
marshal str W 0.265 R 0.078
c:\Python34\python -u "serialization_benchmark.py"
1000 times 1000 elements:
json int W 0.203 R 0.140 6 kB
pickle int W 0.047 R 0.062 3 kB
pickle int W 0.031 R 0.062 3 kB
marshal int W 0.031 R 0.047 5 kB
json float W 1.935 R 0.749 19 kB
pickle float W 0.047 R 0.062 9 kB
pickle float W 0.047 R 0.062 9 kB
marshal float W 0.047 R 0.047 9 kB
json str W 0.281 R 0.187 36 kB
pickle str W 0.125 R 0.140 35 kB
pickle str W 0.125 R 0.140 35 kB
marshal str W 0.094 R 0.078 34 kB
v1.1 zlib:
c:\Python34\python -u "serialization_benchmark.py"
1000 times 1000 elements:
json int 0.686 sW 0.187 sR 3 kB
pickle int 0.187 sW 0.078 sR 2 kB
pickle int 0.187 sW 0.094 sR 2 kB
marshal int 0.702 sW 0.094 sR 3 kB
json float 3.325 sW 0.874 sR 10 kB
pickle float 0.546 sW 0.140 sR 8 kB
pickle float 0.546 sW 0.125 sR 8 kB
marshal float 0.468 sW 0.109 sR 8 kB
json str 2.590 sW 0.608 sR 20 kB
pickle str 2.496 sW 0.452 sR 20 kB
pickle str 2.418 sW 0.421 sR 20 kB
marshal str 1.981 sW 0.374 sR 20 kB
v1.1 bz2:
c:\Python34\python -u "serialization_benchmark.py"
1000 times 1000 elements:
json int 1.188 sW 0.446 sR 2 kB
pickle int 1.263 sW 0.317 sR 2 kB
pickle int 1.295 sW 0.271 sR 2 kB
marshal int 1.627 sW 0.270 sR 2 kB
json float 4.828 sW 1.706 sR 8 kB
pickle float 2.737 sW 0.749 sR 8 kB
pickle float 2.699 sW 0.718 sR 8 kB
marshal float 2.590 sW 0.733 sR 8 kB
json str 5.179 sW 1.778 sR 17 kB
pickle str 4.883 sW 1.888 sR 17 kB
pickle str 4.849 sW 1.857 sR 17 kB
marshal str 4.782 sW 1.741 sR 17 kB
c:\Python34\python -u "serialization_benchmark_nocompress.py"
10 times 100000 elements:
json int 0.187 sW 0.140 sR 589 kB
pickle int 0.031 sW 0.062 sR 298 kB
pickle int 0.031 sW 0.047 sR 298 kB
marshal int 0.047 sW 0.047 sR 500 kB
json float 1.778 sW 0.686 sR 1919 kB
pickle float 0.062 sW 0.047 sR 900 kB
pickle float 0.047 sW 0.062 sR 900 kB
marshal float 0.047 sW 0.031 sR 900 kB
json str 0.312 sW 0.203 sR 3600 kB
pickle str 0.250 sW 0.156 sR 3501 kB
pickle str 0.250 sW 0.156 sR 3501 kB
marshal str 0.125 sW 0.094 sR 3400 kB
2.7 zlib:
C:\Python27\python.exe -u "serialization_benchmark.py"
10 times 100000 elements:
json int 1.108 sW 0.814 sR 226 kB
pickle int 3.011 sW 1.186 sR 216 kB
cPickle int 0.265 sW 0.094 sR 216 kB
marshal int 1.154 sW 0.078 sR 239 kB
json float 4.509 sW 1.030 sR 906 kB
pickle float 4.025 sW 1.185 sR 797 kB
cPickle float 1.498 sW 0.156 sR 797 kB
marshal float 1.108 sW 0.125 sR 793 kB
json str 3.276 sW 0.780 sR 1982 kB
pickle str 9.034 sW 2.981 sR 2259 kB
cPickle str 4.135 sW 0.686 sR 2259 kB
marshal str 2.980 sW 0.421 sR 1989 kB
zlib:
c:\Python34\python -u "serialization_benchmark.py"
10 times 100000 elements:
json int 1.123 sW 0.218 sR 226 kB
pickle int 0.265 sW 0.094 sR 216 kB
pickle int 0.281 sW 0.078 sR 216 kB
marshal int 1.170 sW 0.078 sR 242 kB
json float 4.227 sW 0.842 sR 906 kB
pickle float 1.529 sW 0.125 sR 797 kB
pickle float 1.529 sW 0.125 sR 797 kB
marshal float 1.154 sW 0.109 sR 794 kB
json str 3.182 sW 0.468 sR 1983 kB
pickle str 3.026 sW 0.452 sR 1966 kB
pickle str 3.074 sW 0.437 sR 1966 kB
marshal str 2.637 sW 0.343 sR 1933 kB
bz2:
c:\Python34\python -u "serialization_benchmark.py"
10 times 100000 elements:
json int 1.061 sW 0.655 sR 177 kB
pickle int 0.499 sW 0.218 sR 171 kB
pickle int 0.499 sW 0.234 sR 171 kB
marshal int 0.608 sW 0.374 sR 169 kB
json float 4.415 sW 2.683 sR 769 kB
pickle float 1.981 sW 1.170 sR 758 kB
pickle float 1.622 sW 0.920 sR 758 kB
marshal float 1.982 sW 1.185 sR 770 kB
json str 5.647 sW 3.931 sR 1711 kB
pickle str 5.381 sW 3.759 sR 1712 kB
pickle str 5.335 sW 3.806 sR 1712 kB
marshal str 5.179 sW 3.650 sR 1711 kB
Python 3.13.12 (tags/v3.13.12:1cbe481, Feb 3 2026, 18:22:25) [MSC v.1944 64 bit (AMD64)] on win32
python bench_serializers.py
100,000 times 10 elements:
marshal int 0.056 sW 0.040 sR 0.096 sT 0.096 sC 55 B
marshal float 0.059 sW 0.037 sR 0.096 sT 0.192 sC 95 B
marshal str 0.053 sW 0.051 sR 0.104 sT 0.297 sC 345 B
marshal dict 0.075 sW 0.136 sR 0.212 sT 0.509 sC 457 B
marshal bytes 0.079 sW 0.056 sR 0.135 sT 0.644 sC 2,060 B
marshal class unmarshallable object
msgpack int 0.110 sW 0.047 sR 0.158 sT 0.158 sC 31 B
msgpack float 0.094 sW 0.044 sR 0.138 sT 0.296 sC 91 B
msgpack str 0.098 sW 0.058 sR 0.155 sT 0.451 sC 341 B
msgpack dict 0.152 sW 0.170 sR 0.322 sT 0.774 sC 442 B
msgpack bytes 0.129 sW 0.062 sR 0.191 sT 0.966 sC 2,022 B
msgpack class can not serialize 'Person' object
pyfory int 0.082 sW 0.110 sR 0.192 sT 0.192 sC 26 B
pyfory float 0.068 sW 0.101 sR 0.169 sT 0.361 sC 86 B
pyfory str 0.088 sW 0.130 sR 0.218 sT 0.579 sC 346 B
pyfory dict 0.131 sW 0.250 sR 0.381 sT 0.960 sC 451 B
pyfory bytes 0.662 sW 0.346 sR 1.008 sT 1.968 sC 2,029 B
pyfory class 1.197 sW 1.737 sR 2.934 sT 4.902 sC 1,219 B
pickle int 0.115 sW 0.066 sR 0.180 sT 0.180 sC 46 B
pickle float 0.109 sW 0.070 sR 0.179 sT 0.359 sC 106 B
pickle str 0.136 sW 0.089 sR 0.225 sT 0.584 sC 366 B
pickle dict 0.212 sW 0.180 sR 0.391 sT 0.976 sC 489 B
pickle bytes 0.148 sW 0.093 sR 0.241 sT 1.217 sC 2,049 B
pickle class 1.366 sW 1.253 sR 2.619 sT 3.836 sC 1,490 B
cbor2 int 0.503 sW 0.139 sR 0.642 sT 0.642 sC 31 B
cbor2 float 0.542 sW 0.138 sR 0.679 sT 1.322 sC 91 B
cbor2 str 0.567 sW 0.170 sR 0.737 sT 2.059 sC 341 B
cbor2 dict 0.719 sW 0.311 sR 1.030 sT 3.089 sC 442 B
cbor2 bytes 0.686 sW 0.170 sR 0.856 sT 3.945 sC 2,022 B
cbor2 class cannot serialize type <class '__main__.Person'>
json int 0.234 sW 0.196 sR 0.430 sT 0.430 sC 60 B
json float 0.702 sW 0.429 sR 1.131 sT 1.562 sC 193 B
json str 0.314 sW 0.203 sR 0.517 sT 2.080 sC 360 B
json dict 0.429 sW 0.321 sR 0.750 sT 2.830 sC 492 B
json bytes Object of type bytes is not JSON serializable
json class Object of type Person is not JSON serializable
10 times 100,000 elements:
marshal int 0.019 sW 0.028 sR 0.047 sT 0.047 sC 500,005 B
marshal float 0.026 sW 0.025 sR 0.050 sT 0.098 sC 900,005 B
marshal str 0.034 sW 0.040 sR 0.074 sT 0.173 sC 3,400,005 B
marshal dict 0.065 sW 0.209 sR 0.274 sT 0.447 sC 4,888,897 B
marshal bytes 0.192 sW 0.068 sR 0.260 sT 0.707 sC 20,500,010 B
marshal class unmarshallable object
msgpack int 0.040 sW 0.028 sR 0.068 sT 0.068 sC 296,082 B
msgpack float 0.030 sW 0.029 sR 0.059 sT 0.126 sC 900,005 B
msgpack str 0.063 sW 0.039 sR 0.103 sT 0.229 sC 3,400,005 B
msgpack dict 0.127 sW 0.279 sR 0.406 sT 0.636 sC 4,788,896 B
msgpack bytes 0.198 sW 0.077 sR 0.275 sT 0.911 sC 20,200,006 B
msgpack class can not serialize 'Person' object
pyfory int 0.019 sW 0.039 sR 0.058 sT 0.058 sC 217,419 B
pyfory float 0.008 sW 0.034 sR 0.042 sT 0.100 sC 800,008 B
pyfory str 0.043 sW 0.061 sR 0.105 sT 0.204 sC 3,400,008 B
pyfory dict 0.067 sW 0.209 sR 0.276 sT 0.480 sC 4,790,471 B
pyfory bytes 0.640 sW 0.245 sR 0.885 sT 1.366 sC 20,200,011 B
pyfory class 1.171 sW 3.560 sR 4.730 sT 6.096 sC 12,000,542 B
pickle int 0.020 sW 0.074 sR 0.093 sT 0.093 sC 297,680 B
pickle float 0.033 sW 0.041 sR 0.074 sT 0.168 sC 900,331 B
pickle str 0.173 sW 0.066 sR 0.239 sT 0.407 sC 3,500,691 B
pickle dict 0.315 sW 0.257 sR 0.572 sT 0.979 sC 5,089,802 B
pickle bytes 0.279 sW 0.097 sR 0.376 sT 1.355 sC 20,302,998 B
pickle class 2.157 sW 2.296 sR 4.453 sT 5.808 sC 14,194,787 B
cbor2 int 0.071 sW 0.095 sR 0.166 sT 0.166 sC 297,163 B
cbor2 float 0.099 sW 0.049 sR 0.148 sT 0.314 sC 900,005 B
cbor2 str 0.168 sW 0.085 sR 0.253 sT 0.567 sC 3,400,005 B
cbor2 dict 0.349 sW 0.264 sR 0.613 sT 1.180 sC 4,788,896 B
cbor2 bytes 0.618 sW 0.161 sR 0.780 sT 1.960 sC 20,200,006 B
cbor2 class cannot serialize type <class '__main__.Person'>
json int 0.084 sW 0.092 sR 0.176 sT 0.176 sC 588,801 B
json float 0.627 sW 0.370 sR 0.997 sT 1.173 sC 1,918,211 B
json str 0.187 sW 0.092 sR 0.278 sT 1.452 sC 3,600,000 B
json dict 0.283 sW 0.353 sR 0.636 sT 2.087 sC 5,288,892 B
json bytes Object of type bytes is not JSON serializable
json class Object of type Person is not JSON serializable
@CTimmerman
Copy link
Author

It appears that Microsoft GitHub's Gist search excludes this entry for some season. Maybe this comment with the words "benchmark", "pickle", and "marshal" will help find it in the future.

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