Skip to main content

Prefetcher

Struct Prefetcher 

Source
pub struct Prefetcher { /* private fields */ }
Expand description

Thread-safe prefetch manager with configurable lookahead window.

This struct encapsulates the prefetch configuration and computes which blocks should be speculatively loaded following a given access. It maintains minimal state (just the window size) and relies on atomic operations for thread safety.

§Thread Safety

Prefetcher is fully thread-safe and can be shared across threads via Arc<Prefetcher>. The window size is stored as an AtomicU32, allowing lock-free reads and updates. Multiple threads can concurrently call get_prefetch_targets without contention.

§Performance

  • Memory footprint: 8 bytes (one AtomicU32)
  • Computation cost: O(window_size) per call to get_prefetch_targets
  • Contention: None (lock-free atomic operations)

§Examples

use hexz_core::cache::prefetch::Prefetcher;

let prefetcher = Prefetcher::new(4);
let targets = prefetcher.get_prefetch_targets(10);
assert_eq!(targets, vec![11, 12, 13, 14]);

Implementations§

Source§

impl Prefetcher

Source

pub fn new(window_size: u32) -> Self

Constructs a new prefetcher with a fixed lookahead window.

The window size determines how many blocks ahead of the current access should be prefetched. A value of 0 disables prefetching entirely, which is appropriate for random access workloads or low-latency storage backends.

§Arguments
  • window_size - Number of blocks to prefetch ahead of the current access. Typical values range from 4 (local storage) to 32 (high-latency cloud backends). Must fit in u32 (practical limit is much lower, usually < 256).
§Returns

Returns a new Prefetcher instance configured with the specified window size.

§Performance
  • Time complexity: O(1)
  • Memory allocation: 8 bytes
§Examples
use hexz_core::cache::prefetch::Prefetcher;

// Aggressive prefetching for high-latency S3 backend
let s3_prefetcher = Prefetcher::new(16);

// Conservative prefetching for local SSD
let ssd_prefetcher = Prefetcher::new(2);

// Disable prefetching for random access workload
let no_prefetch = Prefetcher::new(0);
assert!(no_prefetch.get_prefetch_targets(100).is_empty());
Source

pub fn try_start(&self) -> bool

Attempts to acquire the in-flight guard. Returns true if this caller won the race and should spawn a prefetch thread. The caller must call clear_in_flight when the prefetch completes.

Source

pub fn spawn_count(&self) -> u64

Returns the total number of prefetch operations started since construction.

Source

pub fn clear_in_flight(&self)

Clears the in-flight flag, allowing the next read to spawn a prefetch.

Source

pub fn get_prefetch_targets(&self, current_block: u64) -> Vec<u64>

Computes the block indices that should be speculatively prefetched.

Given the index of a block currently being accessed, this method returns a contiguous sequence of block indices that immediately follow it. The caller (typically File) is responsible for scheduling the actual I/O operations to load these blocks into the cache.

The returned vector contains exactly window_size consecutive block indices, starting from current_block + 1 and ending at current_block + window_size. If prefetching is disabled (window_size == 0), returns an empty vector.

§Arguments
  • current_block - Zero-based index of the block being actively read. This value is used as the anchor point for computing the prefetch range.
§Returns

Returns Vec<u64> containing the block indices to prefetch:

  • Non-empty: [current_block + 1, current_block + 2, ..., current_block + window_size]
  • Empty: If window_size == 0 (prefetching disabled)
§Performance
  • Time complexity: O(window_size) to allocate and populate the vector
  • Space complexity: O(window_size) for the returned vector
  • Typical cost: < 1 µs for window_size ≤ 32
§Integer Overflow

This method performs saturating addition to avoid panics if current_block is near u64::MAX. However, in practice, block indices are bounded by the snapshot’s logical size, which is typically far below u64::MAX.

§Examples
§Standard Prefetch
use hexz_core::cache::prefetch::Prefetcher;

let prefetcher = Prefetcher::new(5);
let targets = prefetcher.get_prefetch_targets(42);
assert_eq!(targets, vec![43, 44, 45, 46, 47]);
§Disabled Prefetch
use hexz_core::cache::prefetch::Prefetcher;

let prefetcher = Prefetcher::new(0);
let targets = prefetcher.get_prefetch_targets(100);
assert!(targets.is_empty());
§Boundary Case
use hexz_core::cache::prefetch::Prefetcher;

let prefetcher = Prefetcher::new(1);
let targets = prefetcher.get_prefetch_targets(999);
assert_eq!(targets, vec![1000]);
§Integration Notes

The caller must handle:

  • Bounds checking: Ensure prefetch targets do not exceed the stream’s logical size (number of blocks in the snapshot)
  • Cache lookup: Skip prefetching blocks already present in the cache
  • I/O scheduling: Issue async or background reads for the target blocks
  • Error handling: Prefetch failures should not impact the foreground read

See File::read_at_into_uninit for a reference implementation.

Trait Implementations§

Source§

impl Debug for Prefetcher

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more