Hands-on frozenset vs set vs list membership lab: real ops/s for build-once lookup-heavy paths and dict keys, benchmarked on Linux localhost for SREs.
4 min read
After you build once, is frozenset any slower than set for repeated in checks? This lab times lookup-heavy membership on Linux localhost for set, frozenset, and a list baseline — plus frozenset as a dict key (something set cannot do).
Related links:
Lab honesty (1 Oct 2026 IST): Python 3.13.5. 200,000 probes per lookup arm; sizes 64 / 1 024 / 10 000. Containers built once outside the timer. Affiliates: 0. Complements the set-vs-list lab by adding frozenset and hashability.
Verdict up front: at n=1 024, set ~23.3M/s and frozenset ~23.2M (~0.997× — a wash). List ~0.26M (~90× behind). At n=10 000 set vs list ~821×. Prefer frozenset when you need immutability or dict/set nesting.
| Arm | Pattern |
|---|---|
set lookup | x in s after set(members) |
frozenset lookup | x in fs after frozenset(members) |
list lookup | linear x in lst baseline |
| build | set(src) / frozenset(src) from list |
| dict key | frozenset key vs tuple-of-sorted stand-in |
Script: lab-evidence/62-frozenset-vs-set-membership/results/run_lab.py.
| Arm | ops/s | ns/op |
|---|---|---|
| set n=64 | 25,477,480 | 39.3 |
| frozenset n=64 | 26,037,110 | 38.4 |
| list n=64 | 3,899,245 | 256.5 |
| set n=1 024 | 23,272,129 | 43.0 |
| frozenset n=1 024 | 23,211,976 | 43.1 |
| list n=1 024 | 257,154 | 3888.7 |
| set n=10 000 | 20,921,583 | 47.8 |
| frozenset n=10 000 | 20,850,561 | 48.0 |
| list n=10 000 | 25,486 | 39236.7 |
| Arm | builds/s | ns/build |
|---|---|---|
| set n=1 024 | 142,299 | 7027.5 |
| frozenset n=1 024 | 143,145 | 6985.9 |
| set n=10 000 | 12,288 | 81379.8 |
| frozenset n=10 000 | 12,278 | 81444.9 |
Build set vs frozenset at n=1 024: ~0.994× — also a wash. Pay build once; amortize over lookups.
| Arm | ops/s | ns/op |
|---|---|---|
| frozenset as dict key | 28,092,348 | 35.6 |
| tuple(sorted(...)) key | 18,824,050 | 53.1 |
set raises TypeError as a dict key (unhashable). Frozenset keyed ~1.49× a sorted-tuple stand-in here.
.add / .discard in place.set in a dict — hashability, not speed, forces frozenset.| Need | Prefer |
|---|---|
Hot in checks, may mutate | set |
Hot in checks, fixed membership | frozenset |
| Dict/set of membership sets | frozenset keys |
| Tiny n, one-shot scan | list (rarely) |
Evidence: /workspace/lab-evidence/62-frozenset-vs-set-membership/results/.
frozenset ≈ set on lookups. On this box n=1 024 both sat near ~23M/s while list lagged ~90×; at n=10 000 the list gap grew to ~821×. Use frozenset when immutability or hashability matters — not because it is faster.
Lab evidence
Lab 1 Oct 2026 IST. Python 3.13.5; probes=200000. n=1024 lookup set 23.3M frozenset 23.2M (~0.997x); set vs list ~90x; n=10k set vs list ~821x. Affiliates: 0. Evidence: lab-evidence/62-frozenset-vs-set-membership/.
A hands-on localhost lab measuring set, frozenset, list, and dict-key membership across N, with the real crossover point.
Lab1 Oct 20265 min read
Hands-on bisect.insort vs linear vs set lab: real ops/s for mixed sorted-list insert and membership lookup workloads, measured on Linux localhost (lab).
Summary1 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