Skip to content

Commit c8279c2

Browse files
committed
Replace OrdOffset with OffsetList
1 parent c3ca293 commit c8279c2

File tree

5 files changed

+234
-183
lines changed

5 files changed

+234
-183
lines changed

src/trace/implementations/mod.rs

Lines changed: 94 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ pub mod rhh;
5353
pub use self::ord::OrdValSpine as ValSpine;
5454
pub use self::ord::OrdKeySpine as KeySpine;
5555

56-
use std::ops::{Add, Sub};
57-
use std::convert::{TryInto, TryFrom};
5856
use std::borrow::{Borrow, ToOwned};
5957

6058
use timely::container::columnation::{Columnation, TimelyStack};
@@ -96,10 +94,6 @@ where
9694
pub trait Layout {
9795
/// The represented update.
9896
type Target: Update + ?Sized;
99-
/// Offsets to use from keys into vals.
100-
type KeyOffset: OrdOffset;
101-
/// Offsets to use from vals into updates.
102-
type ValOffset: OrdOffset;
10397
/// Container for update keys.
10498
type KeyContainer:
10599
RetainFrom<<Self::Target as Update>::Key>+
@@ -114,38 +108,34 @@ pub trait Layout {
114108
}
115109

116110
/// A layout that uses vectors
117-
pub struct Vector<U: Update, O: OrdOffset = usize> {
118-
phantom: std::marker::PhantomData<(U, O)>,
111+
pub struct Vector<U: Update> {
112+
phantom: std::marker::PhantomData<U>,
119113
}
120114

121-
impl<U: Update, O: OrdOffset> Layout for Vector<U, O>
115+
impl<U: Update> Layout for Vector<U>
122116
where
123117
U::Key: ToOwned<Owned = U::Key> + Sized + Clone,
124118
U::Val: ToOwned<Owned = U::Val> + Sized + Clone,
125119
{
126120
type Target = U;
127-
type KeyOffset = O;
128-
type ValOffset = O;
129121
type KeyContainer = Vec<U::Key>;
130122
type ValContainer = Vec<U::Val>;
131123
type UpdContainer = Vec<(U::Time, U::Diff)>;
132124
}
133125

134126
/// A layout based on timely stacks
135-
pub struct TStack<U: Update, O: OrdOffset = usize> {
136-
phantom: std::marker::PhantomData<(U, O)>,
127+
pub struct TStack<U: Update> {
128+
phantom: std::marker::PhantomData<U>,
137129
}
138130

139-
impl<U: Update+Clone, O: OrdOffset> Layout for TStack<U, O>
131+
impl<U: Update+Clone> Layout for TStack<U>
140132
where
141133
U::Key: Columnation + ToOwned<Owned = U::Key>,
142134
U::Val: Columnation + ToOwned<Owned = U::Val>,
143135
U::Time: Columnation,
144136
U::Diff: Columnation,
145137
{
146138
type Target = U;
147-
type KeyOffset = O;
148-
type ValOffset = O;
149139
type KeyContainer = TimelyStack<U::Key>;
150140
type ValContainer = TimelyStack<U::Val>;
151141
type UpdContainer = TimelyStack<(U::Time, U::Diff)>;
@@ -168,19 +158,18 @@ impl<T: Clone> PreferredContainer for [T] {
168158
}
169159

170160
/// An update and layout description based on preferred containers.
171-
pub struct Preferred<K: ?Sized, V: ?Sized, T, D, O: OrdOffset = usize> {
172-
phantom: std::marker::PhantomData<(Box<K>, Box<V>, T, D, O)>,
161+
pub struct Preferred<K: ?Sized, V: ?Sized, T, D> {
162+
phantom: std::marker::PhantomData<(Box<K>, Box<V>, T, D)>,
173163
}
174164

175-
impl<K,V,T,R,O> Update for Preferred<K, V, T, R, O>
165+
impl<K,V,T,R> Update for Preferred<K, V, T, R>
176166
where
177167
K: Ord+ToOwned + ?Sized,
178168
K::Owned: Ord+Clone,
179169
V: Ord+ToOwned + ?Sized,
180170
V::Owned: Ord+Clone,
181171
T: Ord+Lattice+timely::progress::Timestamp+Clone,
182172
R: Semigroup+Clone,
183-
O: OrdOffset,
184173
{
185174
type Key = K;
186175
type KeyOwned = K::Owned;
@@ -190,19 +179,16 @@ where
190179
type Diff = R;
191180
}
192181

193-
impl<K, V, T, D, O> Layout for Preferred<K, V, T, D, O>
182+
impl<K, V, T, D> Layout for Preferred<K, V, T, D>
194183
where
195184
K: Ord+ToOwned+PreferredContainer + ?Sized,
196185
K::Owned: Ord+Clone,
197186
V: Ord+ToOwned+PreferredContainer + ?Sized,
198187
V::Owned: Ord+Clone,
199188
T: Ord+Lattice+timely::progress::Timestamp+Clone,
200189
D: Semigroup+Clone,
201-
O: OrdOffset,
202190
{
203-
type Target = Preferred<K, V, T, D, O>;
204-
type KeyOffset = O;
205-
type ValOffset = O;
191+
type Target = Preferred<K, V, T, D>;
206192
type KeyContainer = K::Container;
207193
type ValContainer = V::Container;
208194
type UpdContainer = Vec<(T, D)>;
@@ -239,16 +225,90 @@ impl<T: Columnation> RetainFrom<T> for TimelyStack<T> {
239225
}
240226
}
241227

242-
/// Trait for types used as offsets into an ordered layer.
243-
/// This is usually `usize`, but `u32` can also be used in applications
244-
/// where huge batches do not occur to reduce metadata size.
245-
pub trait OrdOffset: Copy + PartialEq + Add<Output=Self> + Sub<Output=Self> + TryFrom<usize> + TryInto<usize>
246-
{}
228+
use std::convert::TryInto;
247229

248-
impl<O> OrdOffset for O
249-
where
250-
O: Copy + PartialEq + Add<Output=Self> + Sub<Output=Self> + TryFrom<usize> + TryInto<usize>,
251-
{}
230+
/// A list of unsigned integers that uses `u32` elements as long as they are small enough, and switches to `u64` once they are not.
231+
#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Debug, Abomonation)]
232+
pub struct OffsetList {
233+
/// Offsets that fit within a `u32`.
234+
smol: Vec<u32>,
235+
/// Offsets that either do not fit in a `u32`, or are inserted after some offset that did not fit.
236+
chonk: Vec<u64>,
237+
}
238+
239+
impl OffsetList {
240+
/// Inserts the offset, as a `u32` if that is still on the table.
241+
pub fn push(&mut self, offset: usize) {
242+
if self.chonk.is_empty() {
243+
if let Ok(smol) = offset.try_into() {
244+
self.smol.push(smol);
245+
}
246+
else {
247+
self.chonk.push(offset.try_into().unwrap())
248+
}
249+
}
250+
else {
251+
self.chonk.push(offset.try_into().unwrap())
252+
}
253+
}
254+
/// Like `std::ops::Index`, which we cannot implement as it must return a `&usize`.
255+
pub fn index(&self, index: usize) -> usize {
256+
if index < self.smol.len() {
257+
self.smol[index].try_into().unwrap()
258+
}
259+
else {
260+
self.chonk[index - self.smol.len()].try_into().unwrap()
261+
}
262+
}
263+
/// Set the offset at location index.
264+
///
265+
/// Complicated if `offset` does not fit into `self.smol`.
266+
pub fn set(&mut self, index: usize, offset: usize) {
267+
if index < self.smol.len() {
268+
if let Ok(off) = offset.try_into() {
269+
self.smol[index] = off;
270+
}
271+
else {
272+
// Move all `smol` elements from `index` onward to the front of `chonk`.
273+
self.chonk.splice(0..0, self.smol.drain(index ..).map(|x| x.try_into().unwrap()));
274+
self.chonk[index - self.smol.len()] = offset.try_into().unwrap();
275+
}
276+
}
277+
else {
278+
self.chonk[index - self.smol.len()] = offset.try_into().unwrap();
279+
}
280+
}
281+
/// The last element in the list of offsets, if non-empty.
282+
pub fn last(&self) -> Option<usize> {
283+
if self.chonk.is_empty() {
284+
self.smol.last().map(|x| (*x).try_into().unwrap())
285+
}
286+
else {
287+
self.chonk.last().map(|x| (*x).try_into().unwrap())
288+
}
289+
}
290+
/// THe number of offsets in the list.
291+
pub fn len(&self) -> usize {
292+
self.smol.len() + self.chonk.len()
293+
}
294+
/// Allocate a new list with a specified capacity.
295+
pub fn with_capacity(cap: usize) -> Self {
296+
Self {
297+
smol: Vec::with_capacity(cap),
298+
chonk: Vec::new(),
299+
}
300+
}
301+
/// Trim all elements at index `length` and greater.
302+
pub fn truncate(&mut self, length: usize) {
303+
if length > self.smol.len() {
304+
self.chonk.truncate(length - self.smol.len());
305+
}
306+
else {
307+
assert!(self.chonk.is_empty());
308+
self.smol.truncate(length);
309+
}
310+
}
311+
}
252312

253313
pub use self::containers::{BatchContainer, SliceContainer};
254314

0 commit comments

Comments
 (0)