python / python/cpython

Speed up SimpleHTTPRequestHandler.list_directory() by using os.scandir()

Aperta
#151,788 12 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

performance stdlib triaged type-feature
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

SimpleHTTPRequestHandler.list_directory() calls os.listdir() and then, for every entry, os.path.isdir() (a stat) and os.path.islink() (an lstat) — two stat-family syscalls per entry. This is wasted work on any filesystem and dominates listing time for large directories; on network filesystems like NFS, where each call is a round-trip, it becomes severe.

os.scandir() returns the entry type from the directory read itself (POSIX d_type / NFS READDIRPLUS), eliminating the per-entry stats in the common case. CPython already did this migration for os.walk(), glob, and pathlib.Path.iterdir() (gh-117727); http.server was missed.

Benchmark

Directory with 1000 files + 1000 dirs (plus a few symlinks):

  • stat-family syscalls (strace): 4088 → 88 (the 88 is constant interpreter startup; the per-entry loop drops from ~2 syscalls to ~0)
  • local filesystem wall-clock: ~10× faster
  • emulating NFS by injecting per-stat latency: the listing goes from seconds to ~2 ms

Worst case — a mount that returns DT_UNKNOWN — falls back to one cached lstat per entry, which is still fewer calls than today and never worse.

The change is behavior-preserving: DirEntry.is_dir()/is_symlink() match os.path.isdir/os.path.islink semantics (follow-symlinks behavior and return-False-on-error), verified across real dirs/files, symlink-to-dir, symlink-to-file, and broken symlinks. The existing test_httpservers suite passes unchanged.

I have a patch ready and will open a PR.


This issue was prepared with AI assistance (Claude Code); the analysis and benchmarks were reviewed by me.

Linked PRs
  • gh-151789

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia da SimpleHTTPRequestHandler.list_directory() ed esamina la suite di test esistente test_httpservers. Confronta i controlli delle voci di directory con il comportamento di os.scandir(), inclusi i symlink e i casi di fallback, quindi esegui i test del server HTTP; il lavoro è completato quando il comportamento rimane invariato mentre si riducono le chiamate a stat per voce. Una pull request collegata copre già questo lavoro.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
python
Ambito
backend, performance, web-dev
Tipo di issue
Refactoring
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Specificata chiaramente
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.