ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
About

Plate 51

  1. Blog

frozenset vs set: Membership Lab

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.

Aditya Challa·30 September 2026·4 min read

Summary
On this page
  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — lookup (p50)
  5. Build cost (from list)
  6. Hashable bonus — dict keys
  7. Reading it
  8. Pitfalls
  9. When to pick what
  10. Reproduce
  11. Closing

Intro — what this post promises

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:

  • set vs list membership localhost lab
  • enum vs constants localhost lab
  • contextlib vs try/finally localhost lab
  • itemgetter vs lambda sort localhost lab
  • lru_cache hit vs miss localhost lab
  • ThreadPoolExecutor vs sequential localhost lab
  • array vs list ints localhost lab
  • itertools vs python loops localhost lab

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.


Arms

ArmPattern
set lookupx in s after set(members)
frozenset lookupx in fs after frozenset(members)
list lookuplinear x in lst baseline
buildset(src) / frozenset(src) from list
dict keyfrozenset key vs tuple-of-sorted stand-in

Lab topology

probes = 200000 mixed hit/miss from universe (size*4)
membership sizes: 64, 1024, 10000
metric: p50 ops/s (probes)

Script: lab-evidence/62-frozenset-vs-set-membership/results/run_lab.py.


Lead table — lookup (p50)

Armops/sns/op
set n=6425,477,48039.3
frozenset n=6426,037,11038.4
list n=643,899,245256.5
set n=1 02423,272,12943.0
frozenset n=1 02423,211,97643.1
list n=1 024257,1543888.7
set n=10 00020,921,58347.8
frozenset n=10 00020,850,56148.0
list n=10 00025,48639236.7

Build cost (from list)

Armbuilds/sns/build
set n=1 024142,2997027.5
frozenset n=1 024143,1456985.9
set n=10 00012,28881379.8
frozenset n=10 00012,27881444.9

Build set vs frozenset at n=1 024: ~0.994× — also a wash. Pay build once; amortize over lookups.


Hashable bonus — dict keys

Armops/sns/op
frozenset as dict key28,092,34835.6
tuple(sorted(...)) key18,824,05053.1

set raises TypeError as a dict key (unhashable). Frozenset keyed ~1.49× a sorted-tuple stand-in here.


Reading it

  • Lookup parity — frozenset and set share the same hash-table story (~1.00× across sizes).
  • List dies with n — ~90× at 1 024, ~821× at 10 000.
  • Pick frozenset for API contracts — “this membership set will not mutate” and nestable in other sets/dicts.
  • Pick set when you mutate — .add / .discard in place.

Pitfalls

  1. Rebuilding the set every request — then build cost dominates; cache a frozenset.
  2. Using list for “small” membership — even n=64 was ~6.5× faster as a set here.
  3. Assuming frozenset is slower — not on the lookup path in this lab.
  4. Putting a set in a dict — hashability, not speed, forces frozenset.

When to pick what

NeedPrefer
Hot in checks, may mutateset
Hot in checks, fixed membershipfrozenset
Dict/set of membership setsfrozenset keys
Tiny n, one-shot scanlist (rarely)

Reproduce

python3 lab-evidence/62-frozenset-vs-set-membership/results/run_lab.py

Evidence: /workspace/lab-evidence/62-frozenset-vs-set-membership/results/.


Closing

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.

frozensetset membershippython sethash lookupdict keylocalhost labsrefrozenset vs set

Lab evidence

What I found running this

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/.

Notes when a lab post goes up

Occasional email for new hands-on reviews. No sequence and no sponsors.

Related links

  • Plate 09

    set vs frozenset vs list: Membership Lookup Lab

    A hands-on localhost lab measuring set, frozenset, list, and dict-key membership across N, with the real crossover point.

    Observability & SRE · 30 Sept 2026

  • Plate 28

    bisect vs Linear vs set: Lookup Lab

    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).

    30 Sept 2026

  • 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

On this page

  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — lookup (p50)
  5. Build cost (from list)
  6. Hashable bonus — dict keys
  7. Reading it
  8. Pitfalls
  9. When to pick what
  10. Reproduce
  11. Closing
All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove