Skip to content

Optimize PMTiles memory usage and integrate shared caching#18

Merged
groldan merged 3 commits intotileverse-io:mainfrom
groldan:pmtiles_reduce_memory_allocations
Dec 29, 2025
Merged

Optimize PMTiles memory usage and integrate shared caching#18
groldan merged 3 commits intotileverse-io:mainfrom
groldan:pmtiles_reduce_memory_allocations

Conversation

@groldan
Copy link
Contributor

@groldan groldan commented Dec 29, 2025

Refactor the PMTiles implementation to reduce memory footprint and leverage the new shared caching infrastructure.

  • Zero-Allocation Optimizations:
    • Optimized HilbertCurve to use primitive math and binary search for zoom level lookup, eliminating object allocation during tile ID conversion.
    • Replaced ByteBufferInputStream with CompressionUtil utilities that stream directly from SeekableByteChannel through BoundedInputStream and Channels, avoiding intermediate buffer copies.
    • Refactored PMTilesEntry to an interface with value-based implementations (Leaf, Tile) to minimize object overhead for directory entries.
    • Updated PMTilesDirectoryImpl to use binary search on the packed ByteBuffer for entry lookups instead of deserializing all entries into objects.
  • Shared Caching Integration:
    • Integrated PMTilesReader and PMTilesVectorTileStore with CacheManager to use shared cache resources.
    • Implemented DirectoryCache and VectorTileCache as views of the shared cache, ensuring efficient eviction and global memory limits.
  • API Improvements:
    • Updated PMTilesReader API to use TileIndex consistently and expose getTileId for direct access.
    • Removed redundant internal buffering logic in favor of the shared ByteBufferPool and direct channel operations.

This changeset significantly reduces heap pressure when reading large PMTiles archives and improves concurrent read performance.

Refactor caching to use shared Caffeine cache with SubCache support

Introduces a centralized caching infrastructure to optimize memory usage across multiple RangeReader instances.

  • Shared Cache Architecture: Added Cache, CacheManager, and SubCache abstractions in io.tileverse.cache. Multiple logical caches now share a single underlying Caffeine cache instance, allowing for global eviction policies and shared weight limits across the application.
  • RangeReader Integration: Refactored CachingRangeReader to use RangeReaderCache, which acts as a view (sub-cache) of the shared global "tileverse-rangereader-cache", keyed by the source identifier.
  • HTTP Optimizations: Updated HttpRangeReader to use a shared CachedThreadPool for HttpClient.
  • API Updates: CachingRangeReader.Builder now accepts a CacheManager.
  • Improve ByteBufferPool cache locality, stats, and direct buffers clean up

This architecture prevents memory fragmentation and ensures that total cache usage respects global limits rather than per-instance limits.

Introduces a centralized caching infrastructure to optimize memory
usage across multiple RangeReader instances.

- Shared Cache Architecture: Added Cache, CacheManager, and SubCache
  abstractions in io.tileverse.cache. Multiple logical caches now share
  a single underlying Caffeine cache instance, allowing for global eviction
  policies and shared weight limits across the application.
- RangeReader Integration: Refactored CachingRangeReader to use RangeReaderCache,
  which acts as a view (sub-cache) of the shared global "tileverse-rangereader-cache",
  keyed by the source identifier.
- HTTP Optimizations: Updated HttpRangeReader to use a shared CachedThreadPool
  for HttpClient.
- API Updates: CachingRangeReader.Builder now accepts a CacheManager.

  This architecture prevents memory fragmentation and ensures that total cache usage respects global limits rather than
  per-instance limits.
@groldan groldan force-pushed the pmtiles_reduce_memory_allocations branch from c0ef581 to 02cd166 Compare December 29, 2025 22:15
Refactors the PMTiles implementation to reduce memory footprint
and leverage the new shared caching infrastructure.

- Zero-Allocation Optimizations:
  - Optimized HilbertCurve to use primitive math and binary search
    for zoom level lookup, eliminating object allocation during tile ID conversion.
  - Replaced ByteBufferInputStream with CompressionUtil utilities that
    stream directly from SeekableByteChannel through BoundedInputStream and Channels,
    avoiding intermediate buffer copies.
  - Refactored PMTilesEntry to an interface with value-based implementations
    (Leaf, Tile) to minimize object overhead for directory entries.
  - Updated PMTilesDirectoryImpl to use binary search on the packed ByteBuffer
    for entry lookups instead of deserializing all entries into objects.
- Shared Caching Integration:
  - Integrated PMTilesReader and PMTilesVectorTileStore with CacheManager
    to use shared cache resources.
  - Implemented DirectoryCache and VectorTileCache as views of the shared cache,
    ensuring efficient eviction and global memory limits.
- API Improvements:
  - Updated PMTilesReader API to use TileIndex consistently and expose
    getTileId for direct access.
  - Removed redundant internal buffering logic in favor of the shared
    ByteBufferPool and direct channel operations.

This changeset significantly reduces heap pressure when reading large
PMTiles archives and improves concurrent read performance.
@groldan groldan force-pushed the pmtiles_reduce_memory_allocations branch from 02cd166 to 9e45c38 Compare December 29, 2025 22:30
@groldan groldan self-assigned this Dec 29, 2025
@groldan groldan added the enhancement New feature or request label Dec 29, 2025
@groldan groldan merged commit e0f0fe5 into tileverse-io:main Dec 29, 2025
10 checks passed
@groldan groldan deleted the pmtiles_reduce_memory_allocations branch December 29, 2025 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant