Skip to content

Commit 759562a

Browse files
refactor: store valid IDs in serialization context (#8897)
The serialization context only needs registry IDs for filtering, so it now snapshots those IDs instead of retaining the entire registry. --------- Signed-off-by: Joe Isaacs <joe.isaacs@live.co.uk>
1 parent c0d1a4e commit 759562a

5 files changed

Lines changed: 41 additions & 19 deletions

File tree

vortex-array/src/arrays/patched/vtable/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -588,7 +588,7 @@ mod tests {
588588
let session = array_session();
589589
session.arrays().register(Patched);
590590

591-
let ctx = ArrayContext::empty().with_registry(session.arrays().registry().clone());
591+
let ctx = ArrayContext::empty().with_valid_ids(session.arrays().registry().ids());
592592
let serialized = array
593593
.serialize(&ctx, &session, &SerializeOptions::default())
594594
.unwrap();

vortex-array/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,4 +190,4 @@ pub fn legacy_session() -> &'static VortexSession {
190190
&LEGACY_SESSION
191191
}
192192

193-
pub type ArrayContext = Context<ArrayPluginRef>;
193+
pub type ArrayContext = Context;

vortex-file/src/writer.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,8 @@ impl VortexWriteOptions {
200200
// parallel and with an empty context they can register their encodings to the context
201201
// in different order, changing the written bytes from run to run.
202202
let ctx = ArrayContext::new(ALLOWED_ENCODINGS.iter().cloned().sorted().collect())
203-
// Configure a registry just to ensure only known encodings are interned.
204-
.with_registry(self.session.arrays().registry().clone());
203+
// Only permit encodings known to the session.
204+
.with_valid_ids(self.session.arrays().registry().ids());
205205
let dtype = stream.dtype().clone();
206206

207207
let (mut ptr, eof) = SequenceId::root().split();

vortex-layout/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,4 @@ mod strategy;
4242
mod test;
4343
pub mod vtable;
4444

45-
pub type LayoutContext = Context<LayoutEncodingRef>;
45+
pub type LayoutContext = Context;

vortex-session/src/registry.rs

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use parking_lot::RwLock;
2121
use vortex_error::VortexExpect;
2222
use vortex_utils::aliases::DefaultHashBuilder;
2323
use vortex_utils::aliases::dash_map::DashMap;
24+
use vortex_utils::aliases::hash_set::HashSet;
2425

2526
/// Global string interner for [`Id`] values.
2627
static INTERNER: LazyLock<ThreadedRodeo<Spur, DefaultHashBuilder>> =
@@ -227,32 +228,32 @@ impl ReadContext {
227228
/// 1. This object holds an Arc of RwLock internally because we need concurrent access from the
228229
/// layout writer code path. We should update SegmentSink to take an Array rather than
229230
/// ByteBuffer such that serializing arrays is done sequentially.
230-
/// 2. The name is terrible. `Interner<T>` is better, but I want to minimize breakage for now.
231+
/// 2. The name is terrible. `Interner` is better, but I want to minimize breakage for now.
231232
#[derive(Clone, Debug)]
232-
pub struct Context<T> {
233+
pub struct Context {
233234
// TODO(ngates): it's a long story, but if we make SegmentSink and SegmentSource take an
234235
// enum of Segment { Array, DType, Buffer } then we don't actually need a mutable context
235236
// in the LayoutWriter, therefore we don't need a RwLock here and everyone is happier.
236237
ids: Arc<RwLock<Vec<Id>>>,
237-
// Optional registry used to filter the permissible interned items.
238-
registry: Option<Registry<T>>,
238+
// Optional set used to filter the permissible interned IDs.
239+
valid_ids: Option<Arc<HashSet<Id>>>,
239240
}
240241

241-
impl<T> Default for Context<T> {
242+
impl Default for Context {
242243
fn default() -> Self {
243244
Self {
244245
ids: Arc::new(RwLock::new(Vec::new())),
245-
registry: None,
246+
valid_ids: None,
246247
}
247248
}
248249
}
249250

250-
impl<T: Clone> Context<T> {
251+
impl Context {
251252
/// Create a context with the given initial IDs.
252253
pub fn new(ids: Vec<Id>) -> Self {
253254
Self {
254255
ids: Arc::new(RwLock::new(ids)),
255-
registry: None,
256+
valid_ids: None,
256257
}
257258
}
258259

@@ -261,18 +262,18 @@ impl<T: Clone> Context<T> {
261262
Self::default()
262263
}
263264

264-
/// Configure a registry to restrict the permissible set of interned items.
265-
pub fn with_registry(mut self, registry: Registry<T>) -> Self {
266-
self.registry = Some(registry);
265+
/// Restrict the permissible set of interned IDs.
266+
pub fn with_valid_ids(mut self, ids: impl IntoIterator<Item = Id>) -> Self {
267+
self.valid_ids = Some(Arc::new(ids.into_iter().collect()));
267268
self
268269
}
269270

270271
/// Intern an ID, returning its index.
271272
pub fn intern(&self, id: &Id) -> Option<u16> {
272-
if let Some(registry) = &self.registry
273-
&& registry.find(id).is_none()
273+
if let Some(valid_ids) = &self.valid_ids
274+
&& !valid_ids.contains(id)
274275
{
275-
// ID not in registry, cannot intern.
276+
// ID is not valid, cannot intern.
276277
return None;
277278
}
278279

@@ -295,3 +296,24 @@ impl<T: Clone> Context<T> {
295296
self.ids.read().clone()
296297
}
297298
}
299+
300+
#[cfg(test)]
301+
mod tests {
302+
use super::CachedId;
303+
use super::Context;
304+
305+
static VALID: CachedId = CachedId::new("vortex.test.valid");
306+
static INVALID: CachedId = CachedId::new("vortex.test.invalid");
307+
308+
#[test]
309+
fn context_filters_interned_ids() {
310+
let valid = *VALID;
311+
let invalid = *INVALID;
312+
let context = Context::empty().with_valid_ids([valid]);
313+
314+
assert_eq!(context.intern(&valid), Some(0));
315+
assert_eq!(context.intern(&valid), Some(0));
316+
assert_eq!(context.intern(&invalid), None);
317+
assert_eq!(context.to_ids(), [valid]);
318+
}
319+
}

0 commit comments

Comments
 (0)