Struct pagetable::PageTable

source ·
pub struct PageTable<T: Zeroable> { /* private fields */ }
Expand description

A simple 4-level wait-free atomic pagetable. Punches through to the last level and installs any necessary pages along the way.

Works well for big contiguous metadata. Defaults all values to zeroed bits, so this only works with atomic values, as it’s not distinguishable whether a value was ever set to 0 or simply never initialized.

Warning: don’t use this for sparse keyspaces, as any time a key in a 2^16 range is touched for the first time, the zeroed slabs of values and parents (each with 2^16 children) will be created. For 64-bit values (and parent levels that point down) each slab is 8 * 2^16 bytes of memory, or 512kb. It is expected that this page table will be used for very hot global shared metadata.

There are some simple optimizations for when only the lowest bits in the u64 are used, which skips allocation and traversal of parent levels. For tables where only keys 0..2^16 are used, traversals can jump directly to the leaf slab, and avoid allocations.

The same principle is applied for avoiding levels when only the bottom 32 or 48 bits are used for keys.

Examples

use std::sync::atomic::{AtomicU64, Ordering};

let pt = pagetable::PageTable::<AtomicU64>::default();

for i in 0..100_000_000 {
    pt.get(i).fetch_add(1, Ordering::SeqCst);
}

for i in 0..100_000_000 {
    let value = pt.get(i).load(Ordering::SeqCst);
    assert_eq!(value, 1);
}

Implementations§

source§

impl<T: Zeroable> PageTable<T>

source

pub fn get(&self, key: u64) -> &T

Get the AtomicU64 associated with the provided key, installing all required pages if it does not exist yet. Defaults to 0.

Examples found in repository?
examples/bench.rs (line 52)
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
fn main() {
    let before = Instant::now();
    let pt = PageTable::<AtomicUsize>::default();

    for i in 0_u64..(1 << 33) {
        pt.get(i);
    }

    dbg!(before.elapsed());

    dbg!(allocated());
    dbg!(freed());
    dbg!(resident());

    drop(pt);
    println!("after drop:");
    dbg!(before.elapsed());

    dbg!(allocated());
    dbg!(freed());
    dbg!(resident());
}

Trait Implementations§

source§

impl<T: Zeroable> Clone for PageTable<T>

source§

fn clone(&self) -> Self

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl<T: Default + Zeroable> Default for PageTable<T>

source§

fn default() -> PageTable<T>

Returns the “default value” for a type. Read more
source§

impl<T: Zeroable, I: Into<u64>> Index<I> for PageTable<T>

§

type Output = T

The returned type after indexing.
source§

fn index(&self, index: I) -> &Self::Output

Performs the indexing (container[index]) operation. Read more

Auto Trait Implementations§

§

impl<T> RefUnwindSafe for PageTable<T>

§

impl<T> Send for PageTable<T>

§

impl<T> Sync for PageTable<T>

§

impl<T> Unpin for PageTable<T>

§

impl<T> UnwindSafe for PageTable<T>

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere 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, U> Into<U> for Twhere 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> ToOwned for Twhere T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

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

§

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 Twhere U: TryFrom<T>,

§

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.