using fsspec adaptive-readahead cache - #993
Conversation
There was a problem hiding this comment.
Code Review
This pull request migrates the custom prefetching logic from gcsfs to fsspec by replacing the local prefetcher implementation with compatibility re-exports from fsspec.prefetch, and updates the default cache type to adaptive_readahead. The reviewer identified three key issues: a potential AttributeError in ZonalFile due to the removal of _prefetch_engine, the need for a specific fallback cache type (readahead_chunked) for ZonalFile when adaptive_readahead is unavailable, and a potential ImportError when running with older versions of fsspec that lack the prefetch module.
| self.consistency = consistency | ||
| self.checker = get_consistency_checker(consistency) |
There was a problem hiding this comment.
Since self._prefetch_engine has been completely removed from GCSFile.__init__, calling _fetch_range on a ZonalFile instance will raise an AttributeError because ZonalFile._fetch_range (in gcsfs/zonal_file.py line 193) still accesses self._prefetch_engine directly. Defining self._prefetch_engine = None here maintains backward compatibility and prevents this runtime error.
| self.consistency = consistency | |
| self.checker = get_consistency_checker(consistency) | |
| self.consistency = consistency | |
| self.checker = get_consistency_checker(consistency) | |
| self._prefetch_engine = None |
| if "r" in mode and cache_type == "adaptive_readahead": | ||
| if cache_type not in fsspec.core.caches: | ||
| warnings.warn( | ||
| "fsspec adaptive_readahead cache is unavailable in this environment; " | ||
| "falling back to readahead" | ||
| ) | ||
| cache_type = "readahead" |
There was a problem hiding this comment.
When adaptive_readahead is not available in the environment, falling back to "readahead" is appropriate for GCSFile, but for ZonalFile it should fall back to "readahead_chunked" (which was its previous default and is optimized for zonal/gRPC paths). Falling back to "readahead" for ZonalFile could lead to performance degradation.
| if "r" in mode and cache_type == "adaptive_readahead": | |
| if cache_type not in fsspec.core.caches: | |
| warnings.warn( | |
| "fsspec adaptive_readahead cache is unavailable in this environment; " | |
| "falling back to readahead" | |
| ) | |
| cache_type = "readahead" | |
| if "r" in mode and cache_type == "adaptive_readahead": | |
| if cache_type not in fsspec.core.caches: | |
| fallback = "readahead_chunked" if type(self).__name__ == "ZonalFile" else "readahead" | |
| warnings.warn( | |
| f"fsspec adaptive_readahead cache is unavailable in this environment; " | |
| f"falling back to {fallback}" | |
| ) | |
| cache_type = fallback |
| fetcher_fn = default_fetcher | ||
|
|
||
| from .prefetcher import BackgroundPrefetcher | ||
| from fsspec.prefetch import BackgroundPrefetcher |
There was a problem hiding this comment.
If gcsfs is used with an older version of fsspec that does not have fsspec.prefetch, importing BackgroundPrefetcher directly will raise an ImportError and crash concurrent downloads. Wrapping this import in a try-except block and falling back to sequential download (_get_file_request) provides graceful backward compatibility.
| from fsspec.prefetch import BackgroundPrefetcher | |
| try: | |
| from fsspec.prefetch import BackgroundPrefetcher | |
| except ImportError: | |
| warnings.warn( | |
| "fsspec.prefetch is unavailable in this environment; " | |
| "falling back to sequential download" | |
| ) | |
| return await self._get_file_request( | |
| rpath, lpath, headers=headers, callback=callback, **kwargs | |
| ) |
Changes on top of - adaptive-readahead cache in fsspec. fsspec/filesystem_spec#2093