Plate 06
pickle vs json: Round-trip Lab
Hands-on pickle vs json local round-trip lab: real throughput and size for modest dict/list payloads (trusted data), measured on Linux localhost (lab).
Aditya Challa4 min read
Intro — what this post promises
Local object cache / same-host IPC: is pickle faster and smaller than compact json for modest dict/list trees? This lab measures dumps / loads / round-trip ops/s and byte size on Linux localhost.
Security warning: pickle.loads on untrusted bytes is a remote-code-execution hazard. Use pickle only for trusted local data you wrote yourself.
Related links:
- json vs orjson vs msgpack localhost lab
- json dumps compact vs indent localhost lab
- csv reader vs split localhost lab
- copy vs deepcopy localhost lab
- hashlib md5 vs blake2b localhost lab
- bytes vs bytearray localhost lab
- shutil copyfile vs manual localhost lab
- perf_counter vs time localhost lab
Lab honesty (1 Oct 2026 IST): Python 3.13.5; protocols [4, 5] (HIGHEST=5). JSON uses compact separators. Affiliates: 0. Not a rematch of orjson/msgpack (lab 36) or indent formatting (lab 75).
Verdict up front (small, 100 rows): pickle p5 dumps ~25433/s vs json ~7640 (~3.33×); round-trip ~2.64×; size 7,342 B vs 11,368 B (pickle/json ~0.65×). Prefer pickle for trusted local caches; JSON for anything crossing a trust boundary.
Arms
| Arm | Notes |
|---|---|
json.dumps/loads | compact separators=(',', ':') |
pickle protocol 4 / 5 | binary |
| dumps / loads / round-trip | separate timings |
Payloads: tiny (10), small (100), medium (1000) nested row dicts.
Lab topology
Script: lab-evidence/79-pickle-vs-json-roundtrip/results/run_lab.py.
Lead table — small payload (p50)
| Arm | ops/s | bytes |
|---|---|---|
| pickle p5 dumps | 25,433 | 7,342 |
| pickle p5 loads | 21,788 | 7,342 |
| pickle p5 round-trip | 11,613 | 7,342 |
| json dumps | 7,640 | 11,368 |
| json loads | 10,400 | 11,368 |
| json round-trip | 4,395 | 11,368 |
Medium scale & size
| Form | dumps/s | round-trip/s | bytes |
|---|---|---|---|
| pickle p5 | 1,881 | 874 | 74,612 |
| json compact | 776 | 419 | 115,481 |
pickle÷json dumps medium ~2.42×; size ratio ~0.65×. Protocol 5 ≈ 4 here (dumps p5÷p4 small ~0.99×).
Reading it
- Pickle wins trusted local encode/decode on these JSON-friendly dict trees — binary, no UTF-8 number formatting.
- JSON stays the interchange format for APIs, logs, and anything untrusted readers touch.
- Size — pickle was ~35% smaller than compact JSON on small/medium.
- Never
pickle.loadsfrom the network, a user upload, or a shared queue without a hard trust boundary.
Trust boundary checklist
- Did your process write these bytes in this deployment? → pickle may be OK for a local cache file under your lock.
- Did they cross a network, user upload, or multi-tenant queue? → JSON/msgpack/protobuf — never pickle.
- Do non-Python readers need the blob? → JSON (or a schema’d binary format).
Round-trip speed does not override that checklist.
Protocol 4 vs 5
On these pure-dict payloads, protocol 5 was essentially tied with 4. Prefer protocol=5 (or HIGHEST_PROTOCOL) for new local caches anyway — newer opcodes help other object graphs (e.g. large binary out-of-band in some cases). Re-bench if your payload is numpy-heavy or self-referential.
Pitfalls
- Unpickling untrusted input — classic RCE.
- Using pickle across Python major versions / non-Python clients — fragile.
- Pretty JSON as a cache format — waste (see lab 75).
- Assuming protocol 5 always faster — measure; often a wash for pure-Python dicts.
When to pick what
| Need | Prefer |
|---|---|
| Trusted process-local cache | pickle (protocol 5) |
| Human/debuggable / cross-language | JSON |
| Untrusted or multi-tenant data | never pickle |
| Max wire speed + schema | msgpack/orjson (lab 36) |
Reproduce
Evidence: /workspace/lab-evidence/79-pickle-vs-json-roundtrip/results/.
Closing
Pickle for trusted local speed/size; JSON for boundaries. On this box small pickle p5 dumps beat compact JSON by ~3.3× with ~0.65× the bytes — and still must never load strangers’ pickles.
Lab evidence
What I found running this
Lab 1 Oct 2026 IST. Python 3.13.5; pickle protocol=5. small: pickle dumps 25433/s vs json 7640 (~3.33x); roundtrip ~2.64x; size pickle/json ~0.65x. UNSAFE to unpickle untrusted data. Affiliates: 0. Evidence: lab-evidence/79-pickle-vs-json-roundtrip/.
Related links
Plate 17
platform vs os.uname Inventory: Localhost Lab
Hands-on platform.platform vs os.uname host inventory lab: real ops/s plus cache notes, measured on Linux localhost today in this hands-on lab for SREs.
1 Oct 2026
Plate 50
signal vs threading.Event Wakeup: Localhost Lab
Hands-on signal SIGUSR1 vs threading.Event wakeup lab: real p50 latency in microseconds, measured on Linux localhost today in this hands-on lab for SREs.
1 Oct 2026
Plate 76
cmath vs math.hypot Magnitudes: Localhost Lab
Hands-on cmath vs math.hypot magnitude ops lab: real ops/s for abs, polar, and phase, measured on Linux localhost today in this hands-on lab for SREs.
1 Oct 2026