Skip to content

Commit

Permalink
Introduce entry-like vector API in order to reduce interned data copi…
Browse files Browse the repository at this point in the history
…es even more
  • Loading branch information
kvark committed Nov 28, 2018
1 parent 06fe8b5 commit db16047
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 18 deletions.
28 changes: 11 additions & 17 deletions webrender/src/intern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,16 +142,10 @@ impl<S, T, M> DataStore<S, T, M> where S: Debug, T: From<S>, M: Debug {
for update in update_list.updates {
match update.kind {
UpdateKind::Insert => {
let data = data_iter.next().unwrap();
let item = Item {
data: T::from(data),
self.items.entry(update.index).set(Item {
data: T::from(data_iter.next().unwrap()),
epoch: update_list.epoch,
};
if self.items.len() == update.index {
self.items.push(item)
} else {
self.items[update.index] = item;
}
});
}
UpdateKind::Remove => {
self.items[update.index].epoch = Epoch::INVALID;
Expand All @@ -161,6 +155,7 @@ impl<S, T, M> DataStore<S, T, M> where S: Debug, T: From<S>, M: Debug {
}
}
}
debug_assert!(data_iter.next().is_none());
}
}

Expand Down Expand Up @@ -202,6 +197,8 @@ pub struct Interner<S : Eq + Hash + Clone + Debug, D, M> {
update_data: Vec<S>,
/// The current epoch for the interner.
current_epoch: Epoch,
/// Incrementing counter for identifying stable values.
next_uid: usize,
/// The information associated with each interned
/// item that can be accessed by the interner.
local_data: Vec<Item<D>>,
Expand All @@ -216,6 +213,7 @@ impl<S, D, M> Interner<S, D, M> where S: Eq + Hash + Clone + Debug, M: Copy + De
updates: Vec::new(),
update_data: Vec::new(),
current_epoch: Epoch(1),
next_uid: 0,
local_data: Vec::new(),
}
}
Expand Down Expand Up @@ -271,7 +269,7 @@ impl<S, D, M> Interner<S, D, M> where S: Eq + Hash + Clone + Debug, M: Copy + De
index: index as u32,
epoch: self.current_epoch,
uid: ItemUid {
uid: self.map.len(),
uid: self.next_uid,
_marker: PhantomData,
},
_marker: PhantomData,
Expand All @@ -280,18 +278,14 @@ impl<S, D, M> Interner<S, D, M> where S: Eq + Hash + Clone + Debug, M: Copy + De
// Store this handle so the next time it is
// interned, it gets re-used.
self.map.insert(data.clone(), handle);
self.next_uid += 1;

// Create the local data for this item that is
// being interned.
let local_item = Item {
self.local_data.entry(index).set(Item {
epoch: self.current_epoch,
data: f(),
};
if self.local_data.len() == index {
self.local_data.push(local_item);
} else {
self.local_data[index] = local_item;
}
});

handle
}
Expand Down
32 changes: 31 additions & 1 deletion webrender/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const NEARLY_ZERO: f32 = 1.0 / 4096.0;

/// A typesafe helper that separates new value construction from
/// vector growing, allowing LLVM to ideally construct the element in place.
#[must_use]
pub struct Allocation<'a, T: 'a> {
vec: &'a mut Vec<T>,
index: usize,
Expand All @@ -37,8 +36,28 @@ impl<'a, T> Allocation<'a, T> {
}
}

/// An entry into a vector, similar to `std::collections::hash_map::Entry`.
pub enum VecEntry<'a, T: 'a> {
Vacant(Allocation<'a, T>),
Occupied(&'a mut T),
}

impl<'a, T> VecEntry<'a, T> {
#[inline(always)]
pub fn set(self, value: T) {
match self {
VecEntry::Vacant(alloc) => { alloc.init(value); }
VecEntry::Occupied(slot) => { *slot = value; }
}
}
}

pub trait VecHelper<T> {
/// Growns the vector by a single entry, returning the allocation.
fn alloc(&mut self) -> Allocation<T>;
/// Either returns an existing elemenet, or grows the vector by one.
/// Doesn't expect indices to be higher than the current length.
fn entry(&mut self, index: usize) -> VecEntry<T>;
}

impl<T> VecHelper<T> for Vec<T> {
Expand All @@ -52,6 +71,17 @@ impl<T> VecHelper<T> for Vec<T> {
index,
}
}

fn entry(&mut self, index: usize) -> VecEntry<T> {
if index < self.len() {
VecEntry::Occupied(unsafe {
self.get_unchecked_mut(index)
})
} else {
assert_eq!(index, self.len());
VecEntry::Vacant(self.alloc())
}
}
}


Expand Down

0 comments on commit db16047

Please sign in to comment.