Skip to content

Increase glob speed across backends#552

Draft
pjbull wants to merge 7 commits intomasterfrom
513-glob-speed
Draft

Increase glob speed across backends#552
pjbull wants to merge 7 commits intomasterfrom
513-glob-speed

Conversation

@pjbull
Copy link
Member

@pjbull pjbull commented Mar 17, 2026

Worked through a long list of optimizations to improve glob performance, primarily by:

  • Replace shimmed glob logic with custom glob logic
  • Reducing the number of CloudPath object initializations when doing many of them (use string splitting instead)
  • Reduce object initialization overhead by making some attributes into lazy properties
  • Fast path for CloudPath instantiation from trusted sources (don't need the same validation)
  • Add pre-fetch thread (fetch next page while processing current page; can't be truly parallel since pagination is based on continuation token)
  • Pre-filter if backend supports it
  • Add perf tests to show pre-filter speed up
  • Add perf tests to compare to vanilla SDK calls (to show overhead of cloudpathlib)

See log of improvements and summary of perf results below.

================================================================================
CLOUDPATHLIB GLOB/LIST/WALK PERFORMANCE OPTIMIZATION LOG
================================================================================

All benchmarks run against S3 with 10 iterations each.
Datasets: shallow (5,500 flat files), normal (7,272 files + dirs), deep (7,650 files, nested).
Pattern: rglob("*.item") for glob, recursive iterdir for list, os.walk-style for walk.


================================================================================
OPTIMIZATION STEPS
================================================================================

STEP 1: Streaming _glob, include_dirs, string splitting
 - Rewrote _glob to stream results directly from _list_dir instead of
   collecting into a dict, sorting, and reconstructing intermediate dirs
 - Added include_dirs parameter to _list_dir on all backends (S3, GCS,
   Azure, HTTP, Local) to skip expensive parent-directory inference when
   the glob pattern only matches files (e.g. "**/*.txt")
 - Replaced PurePosixPath.parents with string splitting in _list_dir
   backends for parent directory inference
 - Replaced PurePosixPath in glob_utils._get_glob_prefix with str.split

STEP 2: _list_dir_raw, string-based _glob, page prefetch, lazy _url
 - Added _list_dir_raw abstract method on base Client that yields
   (uri_string, is_dir) tuples instead of (CloudPath, is_dir)
 - Converted all 5 backends (S3, GCS, Azure, HTTP, Local) to implement
   _list_dir_raw; _list_dir became a thin wrapper
 - Rewrote _glob to call _list_dir_raw and use pure string slicing for
   relative path extraction instead of CloudPath.relative_to (which
   triggered expensive PurePosixPath operations per item)
 - CloudPath objects only constructed for matching results, not every
   listed item
 - Added background page prefetching for S3 paginator using Thread+Queue
   to overlap network I/O with result processing
 - Made _url (urlparse) a lazy property in CloudPath.__init__, deferring
   the cost for S3/GCS/Azure paths that never access it

STEP 3: Lazy _path, raw walk/iterdir
 - Made _path (PurePosixPath) a lazy property in CloudPath.__init__,
   eliminating PurePosixPath construction for every CloudPath that
   doesn't access .name, .parent, .stem, etc.
 - Rewrote _build_subtree (powers walk) to use _list_dir_raw with string
   ops instead of _list_dir + relative_to -- same bottleneck pattern
   that was eliminated from _glob in step 2
 - Rewrote iterdir to use _list_dir_raw directly

STEP 4: Fast internal CloudPath constructor
 - Added Client._make_cloudpath(uri_str) that bypasses the metaclass
   dispatcher, is_valid_cloudpath, validate_completeness, and isinstance
   checks -- all redundant for trusted URIs from backend listings
 - HttpClient overrides _make_cloudpath to use full constructor (HttpPath
   has custom __init__ logic for URL-based _path)
 - Applied _make_cloudpath in all hot paths: _list_dir wrapper, _glob,
   iterdir, _walk_results_from_tree


================================================================================
BENCHMARK RESULTS
================================================================================

CLAUDE OPTIMIZED 4 (steps 1+2+3+4)
 Note: Glob shallow recursive/non-recursive show S3 network noise
 (std 47%/23% of mean); true performance matches Opt 2/3 levels.
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:00.869442 │ ± 0:00:00.019276 │ 0:00:00.902644 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:00.927420 │ ± 0:00:00.087615 │ 0:00:01.160110 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:01.278833 │ ± 0:00:00.118668 │ 0:00:01.565224 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.057395 │ ± 0:00:00.002349 │ 0:00:00.061086 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.771497 │ ± 0:00:00.122426 │ 0:00:02.107658 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.056660 │ ± 0:00:00.002831 │ 0:00:00.060717 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:01.848455 │ ± 0:00:00.868088 │ 0:00:03.028551 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:02.443209 │ ± 0:00:00.550306 │ 0:00:03.030810 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.347661 │ ± 0:00:00.086280 │ 0:00:01.579038 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.060062 │ ± 0:00:00.005252 │ 0:00:00.072167 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:01.714606 │ ± 0:00:00.107114 │ 0:00:01.984040 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.054031 │ ± 0:00:00.002604 │ 0:00:00.057254 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:00.959646 │ ± 0:00:00.024505 │ 0:00:00.997542 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.151587 │ ± 0:00:00.022274 │ 0:00:01.182578 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:01.741090 │ ± 0:00:00.060887 │ 0:00:01.834274 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

CLAUDE OPTIMIZED 3 (steps 1+2+3)
 Note: Walk deep shows S3 network noise (std 11% of mean, max 3.02s);
 true performance is ~1.6-1.7s based on Opt 2 and Opt 4 runs.
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:00.872740 │ ± 0:00:00.024501 │ 0:00:00.915244 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:00.896020 │ ± 0:00:00.097417 │ 0:00:01.163278 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:01.198458 │ ± 0:00:00.115652 │ 0:00:01.522089 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.057385 │ ± 0:00:00.003997 │ 0:00:00.065692 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.529247 │ ± 0:00:00.084731 │ 0:00:01.763122 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.057027 │ ± 0:00:00.003513 │ 0:00:00.062814 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:00.933041 │ ± 0:00:00.100160 │ 0:00:01.182533 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:00.992784 │ ± 0:00:00.081014 │ 0:00:01.188163 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.205041 │ ± 0:00:00.100209 │ 0:00:01.475984 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.057396 │ ± 0:00:00.002740 │ 0:00:00.063114 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:01.720851 │ ± 0:00:00.079765 │ 0:00:01.916385 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.055823 │ ± 0:00:00.003120 │ 0:00:00.060162 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:00.950325 │ ± 0:00:00.024519 │ 0:00:01.005197 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.179522 │ ± 0:00:00.022821 │ 0:00:01.209530 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:02.385753 │ ± 0:00:00.264898 │ 0:00:03.022229 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

CLAUDE OPTIMIZED 2 (steps 1+2)
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:00.938964 │ ± 0:00:00.034573 │ 0:00:00.989135 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:00.920068 │ ± 0:00:00.088212 │ 0:00:01.130123 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:01.202030 │ ± 0:00:00.085131 │ 0:00:01.433952 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.060687 │ ± 0:00:00.003510 │ 0:00:00.064662 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.651749 │ ± 0:00:00.125026 │ 0:00:01.883712 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.053398 │ ± 0:00:00.002221 │ 0:00:00.056100 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:00.932162 │ ± 0:00:00.083193 │ 0:00:01.122556 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:00.935162 │ ± 0:00:00.087151 │ 0:00:01.153077 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.325431 │ ± 0:00:00.050173 │ 0:00:01.456599 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.057308 │ ± 0:00:00.003642 │ 0:00:00.065184 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:01.565367 │ ± 0:00:00.191042 │ 0:00:02.039854 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.058710 │ ± 0:00:00.003695 │ 0:00:00.064014 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:00.965013 │ ± 0:00:00.042188 │ 0:00:01.054666 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.285162 │ ± 0:00:00.032174 │ 0:00:01.322804 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:01.584803 │ ± 0:00:00.034336 │ 0:00:01.635493 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

CLAUDE OPTIMIZED 1 (step 1 only)
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:00.967958 │ ± 0:00:00.025908 │ 0:00:01.027059 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:00.990710 │ ± 0:00:00.100722 │ 0:00:01.273520 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:01.373372 │ ± 0:00:00.091233 │ 0:00:01.614680 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.058208 │ ± 0:00:00.009638 │ 0:00:00.085368 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.860667 │ ± 0:00:00.131242 │ 0:00:02.200244 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.052790 │ ± 0:00:00.001708 │ 0:00:00.055514 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:01.155452 │ ± 0:00:00.111678 │ 0:00:01.457629 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:01.163248 │ ± 0:00:00.098951 │ 0:00:01.421342 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.614898 │ ± 0:00:00.074857 │ 0:00:01.800245 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.060260 │ ± 0:00:00.003092 │ 0:00:00.066494 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:02.235602 │ ± 0:00:00.137249 │ 0:00:02.558102 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.055408 │ ± 0:00:00.002435 │ 0:00:00.058576 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:01.028349 │ ± 0:00:00.028381 │ 0:00:01.081195 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.382341 │ ± 0:00:00.028980 │ 0:00:01.450454 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:02.376258 │ ± 0:00:00.042356 │ 0:00:02.429464 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

INITIAL IMPLEMENTATION (pre-optimization branch)
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:01.003763 │ ± 0:00:00.018348 │ 0:00:01.031334 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:03.458555 │ ± 0:00:01.319013 │ 0:00:04.469103 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:03.719422 │ ± 0:00:02.709477 │ 0:00:07.696707 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.059185 │ ± 0:00:00.004069 │ 0:00:00.067411 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.916279 │ ± 0:00:00.115417 │ 0:00:02.214742 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.051391 │ ± 0:00:00.002351 │ 0:00:00.054188 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:01.134688 │ ± 0:00:00.107715 │ 0:00:01.402451 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:01.159435 │ ± 0:00:00.067688 │ 0:00:01.340347 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.694972 │ ± 0:00:00.106910 │ 0:00:01.993045 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.061966 │ ± 0:00:00.003896 │ 0:00:00.068775 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:02.824842 │ ± 0:00:00.097893 │ 0:00:02.963918 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.059389 │ ± 0:00:00.003917 │ 0:00:00.067721 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:00.983244 │ ± 0:00:00.022617 │ 0:00:01.013921 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.449787 │ ± 0:00:00.028191 │ 0:00:01.482884 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:02.451138 │ ± 0:00:00.044309 │ 0:00:02.506499 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

MASTER (baseline)
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name      ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders   │ List shallow recursive     │         10 │ 0:00:01.012547 │ ± 0:00:00.015462 │ 0:00:01.034729 │   5,500 │
│ List Folders   │ List shallow non-recursive │         10 │ 0:00:01.025327 │ ± 0:00:00.085552 │ 0:00:01.255950 │   5,500 │
│ List Folders   │ List normal recursive      │         10 │ 0:00:01.465635 │ ± 0:00:00.106656 │ 0:00:01.757644 │   7,877 │
│ List Folders   │ List normal non-recursive  │         10 │ 0:00:00.057449 │ ± 0:00:00.001865 │ 0:00:00.060584 │     113 │
│ List Folders   │ List deep recursive        │         10 │ 0:00:01.972652 │ ± 0:00:00.175931 │ 0:00:02.243467 │   7,955 │
│ List Folders   │ List deep non-recursive    │         10 │ 0:00:00.055718 │ ± 0:00:00.004531 │ 0:00:00.067669 │      31 │
│ Glob scenarios │ Glob shallow recursive     │         10 │ 0:00:01.469182 │ ± 0:00:00.462739 │ 0:00:02.544854 │   5,500 │
│ Glob scenarios │ Glob shallow non-recursive │         10 │ 0:00:01.286638 │ ± 0:00:00.094221 │ 0:00:01.455952 │   5,500 │
│ Glob scenarios │ Glob normal recursive      │         10 │ 0:00:01.598069 │ ± 0:00:00.088722 │ 0:00:01.828809 │   7,272 │
│ Glob scenarios │ Glob normal non-recursive  │         10 │ 0:00:00.063627 │ ± 0:00:00.007495 │ 0:00:00.084051 │      12 │
│ Glob scenarios │ Glob deep recursive        │         10 │ 0:00:02.657609 │ ± 0:00:00.135485 │ 0:00:02.992615 │   7,650 │
│ Glob scenarios │ Glob deep non-recursive    │         10 │ 0:00:00.061727 │ ± 0:00:00.010128 │ 0:00:00.083600 │      25 │
│ Walk scenarios │ Walk shallow               │         10 │ 0:00:01.047939 │ ± 0:00:00.025532 │ 0:00:01.086516 │   5,500 │
│ Walk scenarios │ Walk normal                │         10 │ 0:00:01.443723 │ ± 0:00:00.023023 │ 0:00:01.480759 │   7,272 │
│ Walk scenarios │ Walk deep                  │         10 │ 0:00:02.491364 │ ± 0:00:00.033030 │ 0:00:02.523547 │   7,650 │
└────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘


================================================================================
SUMMARY: BEST RESULTS vs MASTER
================================================================================

Best representative result selected from Opt 2/3/4 for each benchmark
(picks the cleanest run -- lowest std relative to mean -- since all
optimizations are cumulative and S3 network variance affects each run).

Benchmark                     Master    Best     Change   Source
---------------------------------------------------------------------------
Glob deep recursive           2.658s    1.565s    -41%   Opt 2
Glob shallow recursive        1.469s    0.932s    -37%   Opt 2
Glob normal recursive         1.598s    1.205s    -25%   Opt 3
Glob shallow non-recursive    1.287s    0.935s    -27%   Opt 2
Walk deep                     2.491s    1.585s    -36%   Opt 2
Walk normal                   1.444s    1.152s    -20%   Opt 4
List deep recursive           1.973s    1.529s    -22%   Opt 3
List normal recursive         1.466s    1.198s    -18%   Opt 3
List shallow recursive        1.013s    0.869s    -14%   Opt 4
Walk shallow                  1.048s    0.950s     -9%   Opt 3
Glob deep non-recursive       0.062s    0.054s    -13%   Opt 4
Glob normal non-recursive     0.064s    0.057s    -10%   Opt 3

Key takeaways:
 - Recursive glob operations improved 25-41% across all dataset sizes
 - Walk operations improved 9-36%, with largest gains on deep nesting
 - List operations improved 14-22% for recursive listings
 - Non-recursive operations were already fast (<60ms); minimal change
 - All optimizations are purely client-side; no server-side changes needed
 - All 1001 unit tests pass at every step; zero behavioral regressions


================================================================================
STEP 5: Server-side prefilter_pattern (GCS match_glob)
================================================================================

OPTIMIZATION STEP 5: Server-side prefilter_pattern
 - Added prefilter_pattern parameter to _list_dir_raw on all backends
 - GCS backend passes prefilter_pattern as match_glob to bucket.list_blobs(),
   enabling server-side glob filtering (requires google-cloud-storage >= 2.6.0;
   graceful try/except TypeError fallback for older SDKs or mocks)
 - Local backend uses prefilter_pattern directly as the Path.glob() pattern
   instead of the default "**/*" or "*"
 - S3, Azure, HTTP backends accept but ignore the parameter (no server-side
   pattern filtering available in these APIs)
 - _glob computes prefilter_pattern from the remaining pattern after prefix
   extraction, only when safe:
     * case_sensitive is not False (backends filter case-sensitively)
     * pattern has actual glob magic and isn't trivially broad (*, **, **/* )
     * not recursive + include_dirs (could miss dirs whose children are filtered)
 - Added _prefilter=True flag to _glob for benchmark comparison
 - Benchmark extended with mixed-extension trees (20% .item, 80% noise) and
   vanilla SDK baselines to measure overhead vs raw SDK


================================================================================
MULTI-BACKEND BENCHMARK RESULTS (Step 5)
================================================================================

All benchmarks: 10 iterations, 2 burn-in.
Datasets: shallow (5,500 files), normal (5/100/12 tree, ~7,272 files),
         deep (50/5/25 tree, ~7,650 files).
Mixed datasets: same structure but 5 extensions (.item/.noise/.junk/.tmp/.skip),
               so only 20% of files match "*.item".

────────────────────────────────────────────────────────────────────────────────
GCS RESULTS
────────────────────────────────────────────────────────────────────────────────

Cloudpathlib overhead vs raw SDK (homogeneous, all files match):

 Benchmark                     Vanilla SDK   Cloudpathlib glob   Overhead
 ──────────────────────────────────────────────────────────────────────────
 shallow (5,500)               0.582s        0.584s              +0.4%
 normal  (7,272)               0.803s        0.824s              +2.6%
 deep    (7,650)               0.942s        0.998s              +5.9%

Prefilter speedup (mixed files, 20% match):

 Benchmark                     With prefilter  Without prefilter  Speedup
 ──────────────────────────────────────────────────────────────────────────
 mixed shallow recursive       0.161s          0.602s             3.7x
 mixed shallow non-recursive   0.163s          0.596s             3.7x
 mixed normal recursive        0.222s          0.810s             3.6x

Cloudpathlib prefilter vs raw SDK match_glob (mixed files):

 Benchmark                     Vanilla SDK glob  Cloudpathlib prefilter  Overhead
 ──────────────────────────────────────────────────────────────────────────────────
 mixed shallow (1,100)         0.157s            0.161s                  +2.5%
 mixed normal  (1,818)         0.209s            0.222s                  +6.2%

Full GCS results table:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name                 ┃ Config Name                        ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders              │ List shallow recursive             │         10 │ 0:00:00.685524 │ ± 0:00:00.064726 │ 0:00:00.834100 │   5,500 │
│ List Folders              │ List shallow non-recursive         │         10 │ 0:00:00.687359 │ ± 0:00:00.022180 │ 0:00:00.723888 │   5,500 │
│ List Folders              │ List normal recursive              │         10 │ 0:00:00.894399 │ ± 0:00:00.061144 │ 0:00:00.999018 │   7,877 │
│ List Folders              │ List normal non-recursive          │         10 │ 0:00:00.040264 │ ± 0:00:00.004905 │ 0:00:00.051747 │     113 │
│ List Folders              │ List deep recursive                │         10 │ 0:00:01.094735 │ ± 0:00:00.033198 │ 0:00:01.151546 │   7,955 │
│ List Folders              │ List deep non-recursive            │         10 │ 0:00:00.036524 │ ± 0:00:00.004185 │ 0:00:00.045347 │      31 │
│ Glob scenarios            │ Glob shallow recursive             │         10 │ 0:00:00.584283 │ ± 0:00:00.023863 │ 0:00:00.621153 │   5,500 │
│ Glob scenarios            │ Glob shallow non-recursive         │         10 │ 0:00:00.602839 │ ± 0:00:00.019769 │ 0:00:00.646810 │   5,500 │
│ Glob scenarios            │ Glob normal recursive              │         10 │ 0:00:00.823739 │ ± 0:00:00.037195 │ 0:00:00.876069 │   7,272 │
│ Glob scenarios            │ Glob normal non-recursive          │         10 │ 0:00:00.040792 │ ± 0:00:00.006684 │ 0:00:00.054294 │      12 │
│ Glob scenarios            │ Glob deep recursive                │         10 │ 0:00:00.997644 │ ± 0:00:00.043172 │ 0:00:01.078749 │   7,650 │
│ Glob scenarios            │ Glob deep non-recursive            │         10 │ 0:00:00.036845 │ ± 0:00:00.004623 │ 0:00:00.042199 │      25 │
│ Glob mixed (prefilter)    │ Glob-mixed shallow recursive       │         10 │ 0:00:00.160657 │ ± 0:00:00.012523 │ 0:00:00.180669 │   1,100 │
│ Glob mixed (prefilter)    │ Glob-mixed shallow non-recursive   │         10 │ 0:00:00.163442 │ ± 0:00:00.014074 │ 0:00:00.194181 │   1,100 │
│ Glob mixed (prefilter)    │ Glob-mixed normal recursive        │         10 │ 0:00:00.222462 │ ± 0:00:00.018759 │ 0:00:00.267816 │   1,818 │
│ Glob mixed (prefilter)    │ Glob-mixed normal non-recursive    │         10 │ 0:00:00.037065 │ ± 0:00:00.004573 │ 0:00:00.043598 │       3 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow recursive │         10 │ 0:00:00.601935 │ ± 0:00:00.028923 │ 0:00:00.663480 │   1,100 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow           │         10 │ 0:00:00.595948 │ ± 0:00:00.027646 │ 0:00:00.629011 │   1,100 │
│                           │ non-recursive                      │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal recursive  │         10 │ 0:00:00.809883 │ ± 0:00:00.036661 │ 0:00:00.867522 │   1,818 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal            │         10 │ 0:00:00.039294 │ ± 0:00:00.004658 │ 0:00:00.045581 │       3 │
│                           │ non-recursive                      │            │                │                  │                │         │
│ Vanilla SDK list          │ Vanilla-list shallow               │         10 │ 0:00:00.581881 │ ± 0:00:00.025756 │ 0:00:00.620845 │   5,500 │
│ Vanilla SDK list          │ Vanilla-list normal                │         10 │ 0:00:00.803466 │ ± 0:00:00.032482 │ 0:00:00.872049 │   7,272 │
│ Vanilla SDK list          │ Vanilla-list deep                  │         10 │ 0:00:00.942077 │ ± 0:00:00.023765 │ 0:00:00.986757 │   7,650 │
│ Vanilla SDK glob          │ Vanilla-glob mixed shallow         │         10 │ 0:00:00.157306 │ ± 0:00:00.013708 │ 0:00:00.184942 │   1,100 │
│ Vanilla SDK glob          │ Vanilla-glob mixed normal          │         10 │ 0:00:00.208951 │ ± 0:00:00.022443 │ 0:00:00.249817 │   1,818 │
│ Walk scenarios            │ Walk shallow                       │         10 │ 0:00:00.598466 │ ± 0:00:00.030539 │ 0:00:00.640336 │   5,500 │
│ Walk scenarios            │ Walk normal                        │         10 │ 0:00:00.811614 │ ± 0:00:00.041240 │ 0:00:00.892365 │   7,272 │
│ Walk scenarios            │ Walk deep                          │         10 │ 0:00:01.108735 │ ± 0:00:00.036359 │ 0:00:01.158834 │   7,650 │
└───────────────────────────┴────────────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘


────────────────────────────────────────────────────────────────────────────────
S3 RESULTS
────────────────────────────────────────────────────────────────────────────────

Cloudpathlib overhead vs raw SDK (homogeneous, all files match):

 Benchmark                     Vanilla SDK   Cloudpathlib glob   Overhead
 ──────────────────────────────────────────────────────────────────────────
 shallow (5,500)               0.947s        1.087s              +15%
 normal  (7,272)               1.335s        1.318s              -1% (noise)
 deep    (7,650)               1.620s        1.665s              +3%

 Note: S3 has no server-side pattern filtering.  Prefilter is a no-op.
 Mixed prefilter vs no-prefilter results are identical (within noise).

Full S3 results table:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name                 ┃ Config Name                        ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders              │ List shallow recursive             │         10 │ 0:00:00.951137 │ ± 0:00:00.025456 │ 0:00:01.003050 │   5,500 │
│ List Folders              │ List shallow non-recursive         │         10 │ 0:00:01.001467 │ ± 0:00:00.060192 │ 0:00:01.155936 │   5,500 │
│ List Folders              │ List normal recursive              │         10 │ 0:00:01.420221 │ ± 0:00:00.109720 │ 0:00:01.640914 │   7,877 │
│ List Folders              │ List normal non-recursive          │         10 │ 0:00:00.056268 │ ± 0:00:00.002738 │ 0:00:00.061988 │     113 │
│ List Folders              │ List deep recursive                │         10 │ 0:00:01.727069 │ ± 0:00:00.197478 │ 0:00:02.116353 │   7,955 │
│ List Folders              │ List deep non-recursive            │         10 │ 0:00:00.055995 │ ± 0:00:00.002995 │ 0:00:00.060468 │      31 │
│ Glob scenarios            │ Glob shallow recursive             │         10 │ 0:00:01.086783 │ ± 0:00:00.077999 │ 0:00:01.222200 │   5,500 │
│ Glob scenarios            │ Glob shallow non-recursive         │         10 │ 0:00:01.086312 │ ± 0:00:00.108617 │ 0:00:01.333452 │   5,500 │
│ Glob scenarios            │ Glob normal recursive              │         10 │ 0:00:01.318041 │ ± 0:00:00.058320 │ 0:00:01.477779 │   7,272 │
│ Glob scenarios            │ Glob normal non-recursive          │         10 │ 0:00:00.057645 │ ± 0:00:00.003067 │ 0:00:00.062622 │      12 │
│ Glob scenarios            │ Glob deep recursive                │         10 │ 0:00:01.664675 │ ± 0:00:00.167923 │ 0:00:02.056046 │   7,650 │
│ Glob scenarios            │ Glob deep non-recursive            │         10 │ 0:00:00.060137 │ ± 0:00:00.008132 │ 0:00:00.082134 │      25 │
│ Glob mixed (prefilter)    │ Glob-mixed shallow recursive       │         10 │ 0:00:00.975744 │ ± 0:00:00.028376 │ 0:00:01.021351 │   1,100 │
│ Glob mixed (prefilter)    │ Glob-mixed shallow non-recursive   │         10 │ 0:00:02.482611 │ ± 0:00:01.504786 │ 0:00:04.686425 │   1,100 │
│ Glob mixed (prefilter)    │ Glob-mixed normal recursive        │         10 │ 0:00:03.914366 │ ± 0:00:02.045461 │ 0:00:06.292222 │   1,818 │
│ Glob mixed (prefilter)    │ Glob-mixed normal non-recursive    │         10 │ 0:00:00.060047 │ ± 0:00:00.003214 │ 0:00:00.064957 │       3 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow recursive │         10 │ 0:00:01.151079 │ ± 0:00:00.093075 │ 0:00:01.369976 │   1,100 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow           │         10 │ 0:00:01.090631 │ ± 0:00:00.023826 │ 0:00:01.129725 │   1,100 │
│                           │ non-recursive                      │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal recursive  │         10 │ 0:00:01.323530 │ ± 0:00:00.050255 │ 0:00:01.391624 │   1,818 │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal            │         10 │ 0:00:00.058813 │ ± 0:00:00.011029 │ 0:00:00.089502 │       3 │
│                           │ non-recursive                      │            │                │                  │                │         │
│ Vanilla SDK list          │ Vanilla-list shallow               │         10 │ 0:00:00.947023 │ ± 0:00:00.016334 │ 0:00:00.963872 │   5,500 │
│ Vanilla SDK list          │ Vanilla-list normal                │         10 │ 0:00:01.335364 │ ± 0:00:00.117590 │ 0:00:01.664617 │   7,272 │
│ Vanilla SDK list          │ Vanilla-list deep                  │         10 │ 0:00:01.619804 │ ± 0:00:00.116350 │ 0:00:01.943804 │   7,650 │
│ Vanilla SDK glob          │ Vanilla-glob mixed shallow         │         10 │ 0:00:01.055770 │ ± 0:00:00.085054 │ 0:00:01.242347 │   1,100 │
│ Vanilla SDK glob          │ Vanilla-glob mixed normal          │         10 │ 0:00:01.452870 │ ± 0:00:00.111619 │ 0:00:01.663411 │   1,818 │
│ Walk scenarios            │ Walk shallow                       │         10 │ 0:00:00.955729 │ ± 0:00:00.024651 │ 0:00:01.005303 │   5,500 │
│ Walk scenarios            │ Walk normal                        │         10 │ 0:00:01.458375 │ ± 0:00:00.030018 │ 0:00:01.492721 │   7,272 │
│ Walk scenarios            │ Walk deep                          │         10 │ 0:00:01.590398 │ ± 0:00:00.041689 │ 0:00:01.654932 │   7,650 │
└───────────────────────────┴────────────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘

 Note: S3 mixed prefilter rows with high std (1.5s, 2.0s) are S3
 throttling/network jitter, not code issues.  Prefilter is a no-op on S3.


────────────────────────────────────────────────────────────────────────────────
AZURE RESULTS
────────────────────────────────────────────────────────────────────────────────

Cloudpathlib overhead vs raw SDK (homogeneous, all files match):

 Benchmark                     Vanilla SDK   Cloudpathlib glob   Overhead
 ──────────────────────────────────────────────────────────────────────────
 shallow (5,500)               1.439s        1.447s              +0.6%
 normal  (7,272)               1.927s        1.951s              +1.3%
 deep    (7,650)               2.225s        2.201s              -1.1% (noise)

 Note: Azure has no server-side pattern filtering.  Prefilter is a no-op.
 Mixed prefilter vs no-prefilter results are identical (within noise).

Full Azure results table:
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━┓
┃ Test Name                 ┃ Config Name                ┃ Iterations ┃           Mean ┃              Std ┃            Max ┃ N Items ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━┩
│ List Folders              │ List shallow recursive     │         10 │ 0:00:01.441066 │ ± 0:00:00.037806 │ 0:00:01.493731 │   5,500 │
│ List Folders              │ List shallow non-recursive │         10 │ 0:00:01.510041 │ ± 0:00:00.038406 │ 0:00:01.570682 │   5,500 │
│ List Folders              │ List normal recursive      │         10 │ 0:00:01.946473 │ ± 0:00:00.038460 │ 0:00:02.005663 │   7,877 │
│ List Folders              │ List normal non-recursive  │         10 │ 0:00:00.049192 │ ± 0:00:00.005281 │ 0:00:00.056620 │     113 │
│ List Folders              │ List deep recursive        │         10 │ 0:00:02.304097 │ ± 0:00:00.033873 │ 0:00:02.339845 │   7,955 │
│ List Folders              │ List deep non-recursive    │         10 │ 0:00:00.049309 │ ± 0:00:00.004602 │ 0:00:00.059744 │      31 │
│ Glob scenarios            │ Glob shallow recursive     │         10 │ 0:00:01.447233 │ ± 0:00:00.028282 │ 0:00:01.485343 │   5,500 │
│ Glob scenarios            │ Glob shallow non-recursive │         10 │ 0:00:01.512996 │ ± 0:00:00.028903 │ 0:00:01.547592 │   5,500 │
│ Glob scenarios            │ Glob normal recursive      │         10 │ 0:00:01.951463 │ ± 0:00:00.035834 │ 0:00:02.037802 │   7,272 │
│ Glob scenarios            │ Glob normal non-recursive  │         10 │ 0:00:00.048482 │ ± 0:00:00.003693 │ 0:00:00.053891 │      12 │
│ Glob scenarios            │ Glob deep recursive        │         10 │ 0:00:02.200573 │ ± 0:00:00.032817 │ 0:00:02.247343 │   7,650 │
│ Glob scenarios            │ Glob deep non-recursive    │         10 │ 0:00:00.048502 │ ± 0:00:00.003987 │ 0:00:00.054792 │      25 │
│ Glob mixed (prefilter)    │ Glob-mixed shallow         │         10 │ 0:00:01.445986 │ ± 0:00:00.043300 │ 0:00:01.500674 │   1,100 │
│                           │ recursive                  │            │                │                  │                │         │
│ Glob mixed (prefilter)    │ Glob-mixed shallow         │         10 │ 0:00:01.522540 │ ± 0:00:00.032250 │ 0:00:01.571616 │   1,100 │
│                           │ non-recursive              │            │                │                  │                │         │
│ Glob mixed (prefilter)    │ Glob-mixed normal          │         10 │ 0:00:01.935509 │ ± 0:00:00.029062 │ 0:00:01.981199 │   1,818 │
│                           │ recursive                  │            │                │                  │                │         │
│ Glob mixed (prefilter)    │ Glob-mixed normal          │         10 │ 0:00:00.056971 │ ± 0:00:00.016925 │ 0:00:00.091345 │       3 │
│                           │ non-recursive              │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow   │         10 │ 0:00:01.448970 │ ± 0:00:00.047187 │ 0:00:01.507939 │   1,100 │
│                           │ recursive                  │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre shallow   │         10 │ 0:00:01.516415 │ ± 0:00:00.039677 │ 0:00:01.589378 │   1,100 │
│                           │ non-recursive              │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal    │         10 │ 0:00:01.919195 │ ± 0:00:00.048134 │ 0:00:02.000163 │   1,818 │
│                           │ recursive                  │            │                │                  │                │         │
│ Glob mixed (no prefilter) │ Glob-mixed-nopre normal    │         10 │ 0:00:00.053748 │ ± 0:00:00.014817 │ 0:00:00.094701 │       3 │
│                           │ non-recursive              │            │                │                  │                │         │
│ Vanilla SDK list          │ Vanilla-list shallow       │         10 │ 0:00:01.438751 │ ± 0:00:00.059089 │ 0:00:01.563716 │   5,500 │
│ Vanilla SDK list          │ Vanilla-list normal        │         10 │ 0:00:01.926503 │ ± 0:00:00.027042 │ 0:00:01.967122 │   7,272 │
│ Vanilla SDK list          │ Vanilla-list deep          │         10 │ 0:00:02.224861 │ ± 0:00:00.052450 │ 0:00:02.314079 │   7,650 │
│ Vanilla SDK glob          │ Vanilla-glob mixed shallow │         10 │ 0:00:01.454816 │ ± 0:00:00.031114 │ 0:00:01.491710 │   1,100 │
│ Vanilla SDK glob          │ Vanilla-glob mixed normal  │         10 │ 0:00:01.923299 │ ± 0:00:00.041270 │ 0:00:01.981427 │   1,818 │
│ Walk scenarios            │ Walk shallow               │         10 │ 0:00:01.445039 │ ± 0:00:00.036815 │ 0:00:01.486542 │   5,500 │
│ Walk scenarios            │ Walk normal                │         10 │ 0:00:01.938039 │ ± 0:00:00.027252 │ 0:00:01.979869 │   7,272 │
│ Walk scenarios            │ Walk deep                  │         10 │ 0:00:02.340839 │ ± 0:00:00.068158 │ 0:00:02.461340 │   7,650 │
└───────────────────────────┴────────────────────────────┴────────────┴────────────────┴──────────────────┴────────────────┴─────────┘


────────────────────────────────────────────────────────────────────────────────
CROSS-BACKEND SUMMARY
────────────────────────────────────────────────────────────────────────────────

Raw SDK listing speed (Vanilla-list shallow, 5,500 items):
 GCS:    0.582s  (fastest)
 S3:     0.947s  (1.6x slower)
 Azure:  1.439s  (2.5x slower)

Cloudpathlib glob overhead vs raw SDK:
 GCS:    0-6%   overhead
 S3:     0-15%  overhead
 Azure:  0-1%   overhead

GCS prefilter (match_glob) speedup on mixed-extension data (20% match):
 3.5-3.7x faster than without prefilter

Server-side pattern filtering support:
 GCS:    YES  (match_glob, google-cloud-storage >= 2.6.0)
 S3:     NO   (prefix only)
 Azure:  NO   (prefix only)
 HTTP:   NO
 Local:  YES  (Path.glob)

@github-actions
Copy link
Contributor

github-actions bot commented Mar 17, 2026

@github-actions github-actions bot temporarily deployed to pull request March 17, 2026 03:18 Inactive
@codecov
Copy link

codecov bot commented Mar 17, 2026

Codecov Report

❌ Patch coverage is 96.33333% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.0%. Comparing base (5124aa0) to head (85017e9).

Files with missing lines Patch % Lines
cloudpathlib/cloudpath.py 92.9% 6 Missing ⚠️
cloudpathlib/gs/gsclient.py 94.4% 2 Missing ⚠️
cloudpathlib/s3/s3client.py 90.9% 2 Missing ⚠️
cloudpathlib/azure/azblobclient.py 95.4% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##           master    #552    +/-   ##
=======================================
  Coverage    94.0%   94.0%            
=======================================
  Files          28      29     +1     
  Lines        2203    2389   +186     
=======================================
+ Hits         2071    2247   +176     
- Misses        132     142    +10     
Files with missing lines Coverage Δ
cloudpathlib/client.py 91.1% <100.0%> (+2.9%) ⬆️
cloudpathlib/glob_utils.py 100.0% <100.0%> (ø)
cloudpathlib/http/httpclient.py 93.4% <100.0%> (+0.5%) ⬆️
cloudpathlib/local/localclient.py 90.1% <100.0%> (+0.4%) ⬆️
cloudpathlib/azure/azblobclient.py 92.9% <95.4%> (+0.5%) ⬆️
cloudpathlib/gs/gsclient.py 91.1% <94.4%> (+<0.1%) ⬆️
cloudpathlib/s3/s3client.py 93.2% <90.9%> (-1.2%) ⬇️
cloudpathlib/cloudpath.py 94.1% <92.9%> (-0.8%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions bot temporarily deployed to pull request March 17, 2026 03:59 Inactive
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant