Remove sub-arrays for Values.
This prevents using references and forces extra allocations during queries as we have to adapt the values. Also remove is_empty() as it si currently unused, and needs to be adapted.
This commit is contained in:
@@ -90,23 +90,27 @@ impl Core {
|
||||
// Sort out the space, and create a SpaceDB per reference space
|
||||
let mut space_dbs = vec![];
|
||||
|
||||
for space in spaces {
|
||||
// Filter the points of this space, and encode them before creating the index.
|
||||
let filtered = space_objects
|
||||
.iter()
|
||||
.filter_map(|object| {
|
||||
if object.space_id() == space.name() {
|
||||
let position: Vec<f64> = object.position().into();
|
||||
Some(SpaceSetObject::new(
|
||||
space.name(),
|
||||
space.encode(&position).unwrap(),
|
||||
*object.value(),
|
||||
))
|
||||
// We cannot return less that the total number of individual Ids stored
|
||||
// in the index for a full-volume query.
|
||||
let max_elements = if let Some(elem) = max_elements {
|
||||
Some(elem.max(properties.len()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
for space in spaces {
|
||||
// Filter the points of this space, and encode them before creating the index.
|
||||
let mut filtered = space_objects
|
||||
.iter()
|
||||
.filter(|object| object.space_id() == space.name())
|
||||
// Clone only the selected objects, not all of them!
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for object in filtered.iter_mut() {
|
||||
let position: Vec<f64> = object.position().into();
|
||||
object.set_position(space.encode(&position).unwrap());
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
space_dbs.push(SpaceDB::new(&space, filtered, scales.clone(), max_elements))
|
||||
}
|
||||
@@ -119,18 +123,6 @@ impl Core {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the given space_id is referenced in the current core.
|
||||
pub fn is_empty(&self, space_id: &str) -> bool {
|
||||
for s in &self.space_db {
|
||||
if s.name() == space_id {
|
||||
return s.is_empty();
|
||||
}
|
||||
}
|
||||
|
||||
// Not found, so the space is empty.
|
||||
true
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &String {
|
||||
&self.title
|
||||
}
|
||||
|
||||
@@ -93,18 +93,6 @@ impl DataBase {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the given space_id is referenced in the DB.
|
||||
fn is_empty(&self, id: &str) -> bool {
|
||||
for s in self.cores.keys() {
|
||||
let core: &Core = self.cores.find(s)[0];
|
||||
if !core.is_empty(id) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn check_exactly_one<'t, T>(list: &[&'t T], name: &str, value: &str) -> Result<&'t T, String> {
|
||||
if list.len() > 1 {
|
||||
Err(format!(
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
|
||||
use super::space::Coordinate;
|
||||
use super::space::Position;
|
||||
use super::space::Shape;
|
||||
use super::space::Space;
|
||||
@@ -18,7 +16,6 @@ use super::CoreQueryParameters;
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct SpaceDB {
|
||||
reference_space: String,
|
||||
values: Vec<Coordinate>,
|
||||
resolutions: Vec<SpaceIndex>,
|
||||
}
|
||||
|
||||
@@ -33,21 +30,6 @@ impl SpaceDB {
|
||||
const DIMENSIONS: usize = 3;
|
||||
const CELL_BITS: usize = 10;
|
||||
|
||||
let mut values = space_objects
|
||||
.iter()
|
||||
.map(|object| *object.value())
|
||||
.collect::<HashSet<_>>()
|
||||
.drain()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
values.sort_unstable_by_key(|&c| c.u64());
|
||||
|
||||
space_objects.iter_mut().for_each(|object| {
|
||||
// Update the values to point into the local (shorter) mapping array.
|
||||
let val = values.binary_search(object.value()).unwrap();
|
||||
object.set_value(val.into());
|
||||
});
|
||||
|
||||
// Build the set of SpaceIndices.
|
||||
let mut resolutions = vec![];
|
||||
let mut indices = vec![];
|
||||
@@ -108,9 +90,6 @@ impl SpaceDB {
|
||||
} else {
|
||||
// Generate scales, following max_elements
|
||||
if let Some(max_elements) = max_elements {
|
||||
// We cannot return less that the total number of individual Ids stored
|
||||
// in the index for a full-volume query.
|
||||
let max_elements = max_elements.max(values.len());
|
||||
let mut count = 0;
|
||||
|
||||
// The next index should contain at most half the number of
|
||||
@@ -127,8 +106,12 @@ impl SpaceDB {
|
||||
// Generate coarser indices, until we reach the expect max_element
|
||||
// values or we can't define bigger bit shift.
|
||||
loop {
|
||||
// Make sure we do not shift more position than available
|
||||
let shift = if count >= 31 { 31 } else { count };
|
||||
// Make sure we do not shift more position than available as well.
|
||||
if space_objects.len() <= max_elements || count > 31 {
|
||||
break;
|
||||
}
|
||||
let shift = count;
|
||||
|
||||
count += 1;
|
||||
space_objects = space_objects
|
||||
.into_iter()
|
||||
@@ -162,10 +145,6 @@ impl SpaceDB {
|
||||
vec![count, count, count],
|
||||
shift,
|
||||
));
|
||||
|
||||
if space_objects.len() <= max_elements || count == std::u32::MAX {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate indices as long as max is smaller than the number of point located in the whole space.
|
||||
@@ -206,7 +185,6 @@ impl SpaceDB {
|
||||
|
||||
SpaceDB {
|
||||
reference_space: reference_space.name().clone(),
|
||||
values,
|
||||
resolutions,
|
||||
}
|
||||
}
|
||||
@@ -227,11 +205,6 @@ impl SpaceDB {
|
||||
self.resolutions.len() - 1
|
||||
}
|
||||
|
||||
// Is this Space DB empty?
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.values.is_empty()
|
||||
}
|
||||
|
||||
fn resolution_from_volume(&self, volume: f64) -> usize {
|
||||
for i in 0..self.resolutions.len() {
|
||||
if volume <= self.resolutions[i].threshold() {
|
||||
@@ -302,13 +275,6 @@ impl SpaceDB {
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the value back to caller's references
|
||||
fn decode_value(&self, objects: &mut Vec<(Position, SpaceFields)>) {
|
||||
for (_, fields) in objects.iter_mut() {
|
||||
fields.set_value(self.values[fields.value().u64() as usize]);
|
||||
}
|
||||
}
|
||||
|
||||
// Search by Id, a.k.a values
|
||||
// The results are in encoded space coordinates.
|
||||
pub fn get_by_id(
|
||||
@@ -317,7 +283,6 @@ impl SpaceDB {
|
||||
parameters: &CoreQueryParameters,
|
||||
) -> Result<Vec<(Position)>, String> {
|
||||
// Is that ID referenced in the current space?
|
||||
if let Ok(offset) = self.values.binary_search(&id.into()) {
|
||||
let index = self.resolution(parameters);
|
||||
|
||||
// Convert the view port to the encoded space coordinates
|
||||
@@ -325,8 +290,8 @@ impl SpaceDB {
|
||||
let view_port = parameters.view_port(space);
|
||||
|
||||
// Select the objects
|
||||
let objects = self.resolutions[index]
|
||||
.find_by_value(&SpaceFields::new(self.name().into(), offset.into()));
|
||||
let objects =
|
||||
self.resolutions[index].find_by_value(&SpaceFields::new(self.name().into(), id.into()));
|
||||
|
||||
let results = if let Some(view_port) = view_port {
|
||||
objects
|
||||
@@ -337,13 +302,7 @@ impl SpaceDB {
|
||||
objects
|
||||
};
|
||||
|
||||
// Convert the Value back to caller's references
|
||||
// Here we do not use decode() as we have a single id value to manage.
|
||||
|
||||
Ok(results)
|
||||
} else {
|
||||
Ok(vec![])
|
||||
}
|
||||
}
|
||||
|
||||
// Search by positions defining a volume.
|
||||
@@ -352,7 +311,7 @@ impl SpaceDB {
|
||||
&self,
|
||||
positions: &[Position],
|
||||
parameters: &CoreQueryParameters,
|
||||
) -> Result<Vec<(Position, SpaceFields)>, String> {
|
||||
) -> Result<Vec<(Position, &SpaceFields)>, String> {
|
||||
let index = self.resolution(parameters);
|
||||
|
||||
// FIXME: Should I do it here, or add the assumption this is a clean list?
|
||||
@@ -361,19 +320,16 @@ impl SpaceDB {
|
||||
//let view_port = parameters.view_port(space);
|
||||
|
||||
// Select the objects
|
||||
let mut results = positions
|
||||
let results = positions
|
||||
.iter()
|
||||
.flat_map(|position| {
|
||||
self.resolutions[index]
|
||||
.find(position)
|
||||
.into_iter()
|
||||
.map(move |fields| (position.clone(), fields.clone()))
|
||||
.map(move |fields| (position.clone(), fields))
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Decode the Value reference
|
||||
self.decode_value(&mut results);
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
@@ -387,7 +343,7 @@ impl SpaceDB {
|
||||
&self,
|
||||
shape: &Shape,
|
||||
parameters: &CoreQueryParameters,
|
||||
) -> Result<Vec<(Position, SpaceFields)>, String> {
|
||||
) -> Result<Vec<(Position, &SpaceFields)>, String> {
|
||||
let index = self.resolution(parameters);
|
||||
|
||||
// Convert the view port to the encoded space coordinates
|
||||
@@ -395,14 +351,7 @@ impl SpaceDB {
|
||||
let view_port = parameters.view_port(space);
|
||||
|
||||
// Select the objects
|
||||
let mut results = self.resolutions[index]
|
||||
.find_by_shape(&shape, &view_port)?
|
||||
.into_iter()
|
||||
.map(|(position, fields)| (position, fields.clone()))
|
||||
.collect();
|
||||
|
||||
// Decode the Value reference
|
||||
self.decode_value(&mut results);
|
||||
let results = self.resolutions[index].find_by_shape(&shape, &view_port)?;
|
||||
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user