Skip to content
This repository was archived by the owner on Oct 5, 2025. It is now read-only.
This repository was archived by the owner on Oct 5, 2025. It is now read-only.

[ADR] Implement Partial Range Caching Strategy for Memory-Efficient Cache Management #41

@groldan

Description

@groldan

Decision Title

Implement Partial Range Caching Strategy for Memory-Efficient Cache Management

Status

  • Proposed (under consideration)
  • Accepted (decision made)
  • Superseded (replaced by newer decision)
  • Deprecated (no longer relevant)

Context

Current caching implementations cache entire ranges as single units, leading to inefficient memory usage when applications request overlapping or partially overlapping ranges. This results in cache pollution, increased memory pressure, and suboptimal cache hit ratios in real-world usage patterns.

Decision

Implement a partial range caching strategy that stores data in fixed-size blocks, enabling cache hits for partial range overlaps and significantly improving memory efficiency and cache performance.

Problem Statement

Current caching limitations impact performance and memory efficiency:

  • Large ranges consume excessive cache memory
  • Overlapping range requests result in cache misses despite data availability
  • Inefficient memory usage leads to premature cache eviction
  • Poor cache hit ratios for realistic access patterns
  • No support for sub-range access within cached data

Considered Options

Option 1: Full Range Caching (Current)

Description: Cache complete requested ranges as single entities

Pros:

  • Simple implementation and reasoning
  • Exact cache hits for identical requests
  • No additional complexity for range reconstruction

Cons:

  • Inefficient memory usage for large ranges
  • No cache benefits for overlapping requests
  • Poor cache hit ratios in practice
  • Memory pressure from large cached ranges

Option 2: Fixed Block Caching

Description: Store data in fixed-size blocks (e.g., 64KB), compose ranges from blocks

Pros:

  • Efficient memory utilization
  • High cache hit ratios for overlapping requests
  • Predictable memory usage patterns
  • Better cache locality and management

Cons:

  • Added complexity for range composition
  • Overhead for block management
  • Potential fragmentation issues

Option 3: Adaptive Block Caching

Description: Dynamic block sizing based on access patterns and content characteristics

Pros:

  • Optimal block sizes for different scenarios
  • Adapts to various data access patterns
  • Maximum efficiency for diverse workloads

Cons:

  • High implementation complexity
  • Difficult to tune and configure
  • Unpredictable memory usage patterns
  • Complex cache management logic

Decision Rationale

Option 2 (Fixed Block Caching) is selected because:

  • Provides optimal balance of complexity and efficiency
  • Delivers predictable memory usage and performance characteristics
  • Enables high cache hit ratios for realistic access patterns
  • Simple enough to implement reliably while providing significant benefits
  • Aligns with existing block alignment optimizations

Architecture Impact

Affected Components

  • Core module (caching infrastructure)
  • Cloud provider modules (S3, Azure, GCS)
  • Caching layer (complete redesign)
  • Authentication system
  • Performance optimizations
  • API design
  • Build system
  • Documentation

Breaking Changes

  • No breaking changes
  • Minor breaking changes (patch release)
  • Major breaking changes (major version bump)

Performance Impact

  • Performance improvement expected
  • Performance neutral
  • May degrade performance (requires optimization)
  • Unknown performance impact (requires analysis)

Security Impact

  • Improves security
  • Security neutral
  • Potential security implications (requires review)

Implementation Plan

Phase 1: Block Cache Infrastructure

  • Design fixed-size block cache with LRU eviction
  • Implement block key generation and indexing
  • Create range-to-blocks mapping algorithms
  • Add block composition for range reconstruction

Phase 2: Cache Integration

  • Integrate block cache with existing RangeReader decorators
  • Implement partial cache hit detection and handling
  • Add cache warming and prefetching for block boundaries
  • Optimize block size based on performance testing

Phase 3: Advanced Features

  • Implement block compression to maximize cache efficiency
  • Add cache statistics and monitoring for block performance
  • Implement intelligent prefetching based on access patterns
  • Add configuration options for different block strategies

Phase 4: Performance Optimization

  • Benchmark block cache vs current implementation
  • Optimize block composition performance
  • Tune cache sizes and eviction policies
  • Validate memory efficiency improvements

Dependencies

  • Block alignment strategy integration
  • Cache eviction policy framework
  • Performance monitoring infrastructure
  • Memory usage optimization techniques

Effort Estimate

  • Medium (1-4 weeks)

Quality Attributes Impact

Performance

Impact: Positive
Details: Expected 2-3x improvement in cache hit ratios, 50% reduction in memory usage

Reliability

Impact: Positive
Details: More predictable memory usage reduces out-of-memory risks

Security

Impact: Neutral
Details: No security implications from caching strategy changes

Maintainability

Impact: Neutral
Details: Added complexity offset by better performance characteristics

Usability

Impact: Positive
Details: Better cache performance improves application responsiveness

Portability

Impact: Neutral
Details: No platform-specific dependencies

Consequences

Positive Consequences

  • Dramatic improvement in cache hit ratios for realistic access patterns
  • Efficient memory utilization enabling larger effective cache sizes
  • Better cache locality and reduced memory pressure
  • Improved performance for overlapping range requests
  • Predictable memory usage patterns for capacity planning

Negative Consequences

  • Added complexity in cache implementation and debugging
  • Potential overhead for block composition operations
  • More complex cache configuration and tuning
  • Increased testing complexity for edge cases

Risks

  • Risk: Block composition overhead negates cache benefits

    • Impact: Medium
    • Probability: Low
    • Mitigation: Performance testing, optimized composition algorithms
  • Risk: Complex implementation introduces bugs

    • Impact: Medium
    • Probability: Medium
    • Mitigation: Comprehensive testing, gradual rollout, fallback mechanisms

Validation & Verification

How will this decision be validated?

  • Performance benchmarks
  • Proof of concept implementation
  • Community feedback
  • Expert review
  • Production testing

Success Criteria

  1. 2x improvement in cache hit ratios for typical access patterns
  2. 50% reduction in memory usage per cached byte
  3. No performance regression for sequential access patterns
  4. Seamless integration with existing caching decorators

Rollback Plan

If block caching proves problematic:

  1. Provide configuration option to disable block caching
  2. Fall back to existing full-range caching implementation
  3. Remove block caching in future release if benefits don't materialize

Documentation Requirements

  • Architecture Decision Record (ADR-014)
  • API documentation update
  • Architecture documentation update
  • Migration guide (if breaking changes)
  • Developer guide updates

Stakeholder Impact

Library Users

Impact: Positive - Better cache performance and memory efficiency

Library Contributors

Impact: Neutral - Added complexity but clearer cache semantics

Ecosystem Integration

Impact: Positive - More efficient memory usage in server applications

Related Decisions

  • Connected to ByteBuffer pooling for efficient block management
  • Related to memory efficiency quality requirements
  • Dependencies on block alignment optimization strategies

References

Timeline

Target Decision Date: Q1 2025
Target Implementation Date: Q2 2025
Target Release: Version 1.1

Additional Context

Block Cache Design

public class BlockCache {
    private final int blockSize;
    private final Cache<BlockKey, ByteBuffer> blocks;
    
    public ByteBuffer read(long start, int length) {
        List<BlockKey> requiredBlocks = calculateRequiredBlocks(start, length);
        List<ByteBuffer> blockData = new ArrayList<>();
        
        for (BlockKey blockKey : requiredBlocks) {
            ByteBuffer block = blocks.get(blockKey);
            if (block == null) {
                block = loadBlock(blockKey);
                blocks.put(blockKey, block);
            }
            blockData.add(block);
        }
        
        return composeRange(blockData, start, length);
    }
    
    private List<BlockKey> calculateRequiredBlocks(long start, int length) {
        long blockStart = (start / blockSize) * blockSize;
        long blockEnd = ((start + length - 1) / blockSize) * blockSize;
        
        List<BlockKey> blocks = new ArrayList<>();
        for (long blockOffset = blockStart; blockOffset <= blockEnd; blockOffset += blockSize) {
            blocks.add(new BlockKey(uri, blockOffset, blockSize));
        }
        return blocks;
    }
}

Cache Performance Comparison

Current Full Range Caching:
- Request: Range[1000, 4096] -> Cache Miss, Load 4096 bytes
- Request: Range[2000, 4096] -> Cache Miss, Load 4096 bytes (50% overlap, no benefit)
- Memory Usage: 8192 bytes for 6144 unique bytes

Block-Based Caching (1KB blocks):
- Request: Range[1000, 4096] -> Load blocks 1024, 2048, 3072, 4096 (4 blocks)
- Request: Range[2000, 4096] -> Cache hits for blocks 2048, 3072, 4096; load 1 new block
- Memory Usage: 5120 bytes for 6144 unique bytes (37% reduction)

Configuration Example

// Block cache configuration
RangeReader reader = S3RangeReader.builder()
    .uri(uri)
    .withCaching(CacheConfig.builder()
        .strategy(CacheStrategy.BLOCK_BASED)
        .blockSize(64 * 1024) // 64KB blocks
        .maxCacheSize(256 * 1024 * 1024) // 256MB cache
        .build())
    .build();

This architectural decision represents a fundamental improvement in caching efficiency that will benefit virtually all use cases while maintaining API compatibility. The block-based approach aligns with modern memory hierarchy optimization principles and provides a foundation for future advanced caching features.

Metadata

Metadata

Assignees

No one assigned

    Labels

    architectureArchitecture decision or designcachingCaching layer and optimizationdecisionArchitecture decision recorddesignDesign and user interface

    Type

    No type

    Projects

    Status

    No status

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions