A measured Linux localhost lab comparing shelve's keyed dbm store with a single pickle blob for full snapshots and random access.
4 min read
Persist a dict of records: shelve (dbm + pickle per key) vs one pickle.dump / load blob. This lab measures write/read rec/s and random-key access on Linux localhost.
It is not pickle vs JSON (lab 79). Here both arms use pickle encoding; the fork is keyed dbm store vs single blob.
Related links:
Lab honesty (1 Oct 2026 IST): Python 3.13.5, pickle.HIGHEST_PROTOCOL. Affiliates: 0. No Docker. Pickle is unsafe for untrusted data — local trusted stores only.
Verdict up front (n=8000): pickle write ~1523630 rec/s vs shelve write ~13436 (~113.0×); full read pickle ~1310138 vs shelve ~147828. 200 keyed gets: shelve ~1.97 ms vs pickle load-all-then-get ~7.54 ms (~3.8×).
| Arm | Pattern |
|---|---|
shelve.open write | one sh[k]=v per record + sync |
pickle.dump | one blob file |
| shelve read all | iterate keys / values |
| pickle read all | load entire dict |
| random access | 200 keys via shelve vs load-all pickle |
Script: lab-evidence/94-shelve-vs-pickle-dict/results/run_lab.py.
| Arm | s | rec/s |
|---|---|---|
| shelve write | 0.595 | 13436 |
| pickle write | 0.0053 | 1523630 |
| shelve read all | 0.0541 | 147828 |
| pickle read all | 0.0061 | 1310138 |
Disk: shelve ~1568768 B vs pickle blob ~979971 B.
| n | shelve write | pickle write |
|---|---|---|
| 500 | 4002 | 1815066 |
| 2000 | 9169 | 1691878 |
| 8000 | 13436 | 1523630 |
| Arm | p50 ms |
|---|---|
| shelve get keys | 1.97 |
| pickle load entire dict then get | 7.54 |
Shelve/dbm keeps a file you can open and fetch one key. A pickle blob is atomic only if you write-temp-and-rename (not measured here). Neither replaces a real database for concurrent writers.
Each assignment pickles a value and updates the dbm map — fine for occasional writes, painful for bulk ingest of thousands of new keys. Bulk-load patterns usually build a dict then pickle once, or use SQLite executemany.
Think of pickle as save game (replace the whole world) and shelve as key/value cabinet (open drawer id_042). Mixing them — rewriting a shelve by deleting all keys then reinserting — usually loses to dump-a-blob. Conversely, shipping a multi-megabyte pickle across the network to change one field is the wrong cabinet.
Evidence: summary.json, bench_shelf_*, bench_blob_*.pkl.
One Linux box, default dbm backend. Not gdbm tuning, not SQLite. Pickle protocol = HIGHEST.
Pickle blob crushed full write/read (~1523630 vs ~13436 rec/s write ). Shelve won keyed access (~1.97 ms vs ~7.54 ms for 200 keys). Choose blob for snapshots; shelve when random access matters.
Lab evidence
Lab 1 Oct 2026 IST. Python 3.13.5. n=8000: pickle write 1523630 rec/s vs shelve 13436; read pickle 1310138 vs shelve 147828. 200-key access: shelve 1.97ms vs pickle load-all 7.54ms. Not JSON lab 79. Affiliates: 0. Evidence: lab-evidence/94-shelve-vs-pickle-dict/.
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).
Summary1 Oct 20264 min read
Hands-on setdefault vs if-not-in vs defaultdict lab: real ops/s for list-append and counter default insert patterns, measured on Linux localhost (lab).
Lab1 Oct 20264 min read
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.
Summary1 Oct 20264 min read