ShopperCove
Menu
All writingBlogTopicsCategoriesAboutRSS
Blog
Categories
Observability & SRE62All categories
Topics
sre111localhost lab102performance70python58javascript47bundle size36benchmarking35node.js35web development21typescript19benchmark16content creation15All topics
About
Loading article…

ShopperCove

Hands-on notes on developer tools, written after the tool has actually been run.

All writingBlogCategoriesTopicsAboutPrivacyRSS

© 2026 ShopperCove

On this page

  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — FIFO cycles/s (p50)
  5. Drain and append baselines
  6. Pitfalls
  7. When to pick what
  8. Reproduce
  9. Closing
  10. FAQ
  11. Is deque faster than list in Python?
  12. Why is list.pop(0) slow?
  13. When should I still use a list?
  1. Blog
  2. /Observability & SRE

deque vs list in Python: Which Is Faster for a Queue?

Hands-on collections.deque vs list queue lab: real FIFO ops/s for append/popleft vs list.pop(0) at several prefill sizes on Linux localhost (eng lab).

30 September 2026·4 min read

Lab

Disclosure

This post contains affiliate links. If you buy through them, I may earn a commission at no extra cost to you. I only make firsthand claims about products I have actually used.

On this page
  1. Intro — what this post promises
  2. Arms
  3. Lab topology
  4. Lead table — FIFO cycles/s (p50)
  5. Drain and append baselines
  6. Pitfalls
  7. When to pick what
  8. Reproduce
  9. Closing
  10. FAQ
  11. Is deque faster than list in Python?
  12. Why is list.pop(0) slow?
  13. When should I still use a list?

Intro — what this post promises

For a FIFO queue in Python, collections.deque beats a list: with append + popleft vs append + pop(0) on Python 3.13.5, deque was about 1.2x faster on a near-empty queue, 2.6x at 1,000 queued items and about 31x at 10,000 (18.6M vs 605k cycles/s). The problem is removing from the front of a list, not lists in general, because list.pop() from the end drained 50k items as fast as deque did.

Related links:

  • 01shoppercove.comlru_cache hit vs miss localhost lab
  • 02shoppercove.comstruct pack vs to_bytes localhost lab
  • 03shoppercove.comset vs list membership localhost lab
  • 04shoppercove.comsorted vs heapq vs bisect localhost lab
  • 05shoppercove.comcopy vs deepcopy localhost lab
  • 06shoppercove.comstring concat vs join localhost lab
  • 07shoppercove.comdataclass vs slots vs dict localhost lab
  • 08shoppercove.comlogging vs print localhost lab

Lab honesty (1 Oct 2026 IST): Python 3.13.5. Affiliates: 0. FIFO cycle = one append + one front pop, keeping length ≈ S.

Verdict up front: at S=0–100 deque is only ~1.2–1.2× list. At S=1 000 already ~2.6×. At S=10 000 ~31× (18.6M vs 605k cycles/s). Draining 50k with pop(0) is ~255k/s vs deque ~31.6M.


Arms

ArmPattern
FIFOprefill S, then M× (append + pop front)
drainprefill N, pop until empty
append-onlygrow from empty (sanity)
list pop() enddrain with pop() — stack, not queue

Lab topology

FIFO S in {0, 100, 1000, 10000, 50000}
M scaled down for large S (still p50 ops/s)
Drain N in {1000, 10000, 50000}
Metric: p50 wall → cycles/s or pops/s

Script: lab-evidence/54-deque-vs-list-queue/results/run_lab.py.


Lead table — FIFO cycles/s (p50)

Prefill Sdequelist pop(0)deque÷list
034,942,18828,243,5931.2×
10034,512,08228,976,0331.2×
1,00032,741,94812,494,5842.6×
10,00018,638,981604,50130.8×
50,0003,049,348119,59625.5×

At S=10k, list pays ~1654 ns/cycle vs deque ~54 ns.


Drain and append baselines

Armops/sns/op
deque drain N=50k31,573,53031.7
list pop(0) drain N=50k255,4873914.1
list pop() end N=50k36,831,95127.2
list append N=100k41,751,38724.0
deque append N=100k36,859,59227.1

list.pop() from the end matches deque drain speed — the bug is front removal, not “lists are slow.”


Pitfalls

  1. Benchmarking empty-queue FIFO only — S≈0 hides the O(n) shift.
  2. Using list as a queue “until it hurts” — at S=1k it already hurts on this box.
  3. Confusing stack (pop()) with queue (pop(0)) — different asymptotics.
  4. Indexing into a deque — O(n) for middle access; use a list if you need random access.

When to pick what

NeedPrefer
FIFO / sliding windowcollections.deque
Stack / LIFOlist + append/pop
Random access + occasional endslist
Append-only buffereither (append is peer)

Reproduce

python3 lab-evidence/54-deque-vs-list-queue/results/run_lab.py

Evidence: /workspace/lab-evidence/54-deque-vs-list-queue/results/.


Closing

list.pop(0) does not stay fine. On this box deque FIFO is ~2.6× at S=1k and ~31× at S=10k. Drain 50k: deque ~32M/s vs list pop(0) ~255k. Use deque for queues; keep list for stacks and random access.

FAQ

Is deque faster than list in Python?

For queue work, yes. Draining 50,000 items, deque.popleft ran at about 31.6M pops/s vs about 255k/s for list.pop(0). For appends only, the two are close (41.8M vs 36.9M/s).

Why is list.pop(0) slow?

Removing the first item shifts every remaining item, so the cost grows with queue length. At 10,000 items a list cycle cost about 1,654 ns vs about 54 ns for deque.

When should I still use a list?

For stacks (append/pop from the end) and random access. Indexing into the middle of a deque is O(n), so use a list when you need positional reads.

collections.dequelist pop(0)fifo queuepopleftpython queuelocalhost labsredeque

Lab evidence

What I found running this

Lab 1 Oct 2026 IST. Python 3.13.5. FIFO append+popleft/pop(0). S=0: deque 34.9M vs list 28.2M (~1.24x). S=1000: deque 32.7M vs list 12.5M (~2.6x). S=10000: deque 18.6M vs list 605k (~31x). S=50000: ~25x. Drain N=50k: deque 31.6M vs list pop(0) 255k. Affiliates: 0. Evidence: lab-evidence/54-deque-vs-list-queue/.

Explore the product

Untested by us. Check what's included, the license and refund terms before you buy.

Ready Client Sites for prebuilt websites

See Ready Client Sites details

Notes when a lab post goes up

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

Explore the product

Untested by us. Check what's included, the license and refund terms before you buy.

Ready Client Sites for prebuilt websites

See Ready Client Sites details

Keep reading

  • islice vs list Slice Windows: Localhost Lab

    Hands-on itertools.islice vs list slice window lab: real ops/s taking ranges from sequences, measured on Linux localhost in this hands-on lab for SREs.

    Lab1 Oct 20264 min read

  • heapq.merge vs sorted(chain): Localhost Lab

    Hands-on heapq.merge vs sorted(chain) multi-way merge: real records/s on pre-sorted lists, measured on Linux localhost today in this hands-on lab for SREs.

    Lab1 Oct 20264 min read

  • mmap Write vs pwrite Region: Localhost Lab

    Hands-on mmap MAP_SHARED write+msync vs pwrite region update: real MB/s with durability labels, measured on Linux localhost in this hands-on lab for SREs.

    Lab1 Oct 20264 min read