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
|
// Sort out the space, and create a SpaceDB per reference space
|
||||||
let mut space_dbs = vec![];
|
let mut space_dbs = vec![];
|
||||||
|
|
||||||
|
// 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 {
|
for space in spaces {
|
||||||
// Filter the points of this space, and encode them before creating the index.
|
// Filter the points of this space, and encode them before creating the index.
|
||||||
let filtered = space_objects
|
let mut filtered = space_objects
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|object| {
|
.filter(|object| object.space_id() == space.name())
|
||||||
if object.space_id() == space.name() {
|
// Clone only the selected objects, not all of them!
|
||||||
let position: Vec<f64> = object.position().into();
|
.cloned()
|
||||||
Some(SpaceSetObject::new(
|
.collect::<Vec<_>>();
|
||||||
space.name(),
|
|
||||||
space.encode(&position).unwrap(),
|
for object in filtered.iter_mut() {
|
||||||
*object.value(),
|
let position: Vec<f64> = object.position().into();
|
||||||
))
|
object.set_position(space.encode(&position).unwrap());
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
space_dbs.push(SpaceDB::new(&space, filtered, scales.clone(), max_elements))
|
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 {
|
pub fn name(&self) -> &String {
|
||||||
&self.title
|
&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> {
|
fn check_exactly_one<'t, T>(list: &[&'t T], name: &str, value: &str) -> Result<&'t T, String> {
|
||||||
if list.len() > 1 {
|
if list.len() > 1 {
|
||||||
Err(format!(
|
Err(format!(
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::HashSet;
|
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
|
|
||||||
use super::space::Coordinate;
|
|
||||||
use super::space::Position;
|
use super::space::Position;
|
||||||
use super::space::Shape;
|
use super::space::Shape;
|
||||||
use super::space::Space;
|
use super::space::Space;
|
||||||
@@ -18,7 +16,6 @@ use super::CoreQueryParameters;
|
|||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
pub struct SpaceDB {
|
pub struct SpaceDB {
|
||||||
reference_space: String,
|
reference_space: String,
|
||||||
values: Vec<Coordinate>,
|
|
||||||
resolutions: Vec<SpaceIndex>,
|
resolutions: Vec<SpaceIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,21 +30,6 @@ impl SpaceDB {
|
|||||||
const DIMENSIONS: usize = 3;
|
const DIMENSIONS: usize = 3;
|
||||||
const CELL_BITS: usize = 10;
|
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.
|
// Build the set of SpaceIndices.
|
||||||
let mut resolutions = vec![];
|
let mut resolutions = vec![];
|
||||||
let mut indices = vec![];
|
let mut indices = vec![];
|
||||||
@@ -108,9 +90,6 @@ impl SpaceDB {
|
|||||||
} else {
|
} else {
|
||||||
// Generate scales, following max_elements
|
// Generate scales, following max_elements
|
||||||
if let Some(max_elements) = 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;
|
let mut count = 0;
|
||||||
|
|
||||||
// The next index should contain at most half the number of
|
// 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
|
// Generate coarser indices, until we reach the expect max_element
|
||||||
// values or we can't define bigger bit shift.
|
// values or we can't define bigger bit shift.
|
||||||
loop {
|
loop {
|
||||||
// Make sure we do not shift more position than available
|
// Make sure we do not shift more position than available as well.
|
||||||
let shift = if count >= 31 { 31 } else { count };
|
if space_objects.len() <= max_elements || count > 31 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let shift = count;
|
||||||
|
|
||||||
count += 1;
|
count += 1;
|
||||||
space_objects = space_objects
|
space_objects = space_objects
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@@ -162,10 +145,6 @@ impl SpaceDB {
|
|||||||
vec![count, count, count],
|
vec![count, count, count],
|
||||||
shift,
|
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.
|
// 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 {
|
SpaceDB {
|
||||||
reference_space: reference_space.name().clone(),
|
reference_space: reference_space.name().clone(),
|
||||||
values,
|
|
||||||
resolutions,
|
resolutions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,11 +205,6 @@ impl SpaceDB {
|
|||||||
self.resolutions.len() - 1
|
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 {
|
fn resolution_from_volume(&self, volume: f64) -> usize {
|
||||||
for i in 0..self.resolutions.len() {
|
for i in 0..self.resolutions.len() {
|
||||||
if volume <= self.resolutions[i].threshold() {
|
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
|
// Search by Id, a.k.a values
|
||||||
// The results are in encoded space coordinates.
|
// The results are in encoded space coordinates.
|
||||||
pub fn get_by_id(
|
pub fn get_by_id(
|
||||||
@@ -317,33 +283,26 @@ impl SpaceDB {
|
|||||||
parameters: &CoreQueryParameters,
|
parameters: &CoreQueryParameters,
|
||||||
) -> Result<Vec<(Position)>, String> {
|
) -> Result<Vec<(Position)>, String> {
|
||||||
// Is that ID referenced in the current space?
|
// Is that ID referenced in the current space?
|
||||||
if let Ok(offset) = self.values.binary_search(&id.into()) {
|
let index = self.resolution(parameters);
|
||||||
let index = self.resolution(parameters);
|
|
||||||
|
|
||||||
// Convert the view port to the encoded space coordinates
|
// Convert the view port to the encoded space coordinates
|
||||||
let space = parameters.db.space(&self.reference_space)?;
|
let space = parameters.db.space(&self.reference_space)?;
|
||||||
let view_port = parameters.view_port(space);
|
let view_port = parameters.view_port(space);
|
||||||
|
|
||||||
// Select the objects
|
// Select the objects
|
||||||
let objects = self.resolutions[index]
|
let objects =
|
||||||
.find_by_value(&SpaceFields::new(self.name().into(), offset.into()));
|
self.resolutions[index].find_by_value(&SpaceFields::new(self.name().into(), id.into()));
|
||||||
|
|
||||||
let results = if let Some(view_port) = view_port {
|
let results = if let Some(view_port) = view_port {
|
||||||
objects
|
objects
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|position| view_port.contains(position))
|
.filter(|position| view_port.contains(position))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
} else {
|
|
||||||
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 {
|
} else {
|
||||||
Ok(vec![])
|
objects
|
||||||
}
|
};
|
||||||
|
|
||||||
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search by positions defining a volume.
|
// Search by positions defining a volume.
|
||||||
@@ -352,7 +311,7 @@ impl SpaceDB {
|
|||||||
&self,
|
&self,
|
||||||
positions: &[Position],
|
positions: &[Position],
|
||||||
parameters: &CoreQueryParameters,
|
parameters: &CoreQueryParameters,
|
||||||
) -> Result<Vec<(Position, SpaceFields)>, String> {
|
) -> Result<Vec<(Position, &SpaceFields)>, String> {
|
||||||
let index = self.resolution(parameters);
|
let index = self.resolution(parameters);
|
||||||
|
|
||||||
// FIXME: Should I do it here, or add the assumption this is a clean list?
|
// 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);
|
//let view_port = parameters.view_port(space);
|
||||||
|
|
||||||
// Select the objects
|
// Select the objects
|
||||||
let mut results = positions
|
let results = positions
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|position| {
|
.flat_map(|position| {
|
||||||
self.resolutions[index]
|
self.resolutions[index]
|
||||||
.find(position)
|
.find(position)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(move |fields| (position.clone(), fields.clone()))
|
.map(move |fields| (position.clone(), fields))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Decode the Value reference
|
|
||||||
self.decode_value(&mut results);
|
|
||||||
|
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -387,7 +343,7 @@ impl SpaceDB {
|
|||||||
&self,
|
&self,
|
||||||
shape: &Shape,
|
shape: &Shape,
|
||||||
parameters: &CoreQueryParameters,
|
parameters: &CoreQueryParameters,
|
||||||
) -> Result<Vec<(Position, SpaceFields)>, String> {
|
) -> Result<Vec<(Position, &SpaceFields)>, String> {
|
||||||
let index = self.resolution(parameters);
|
let index = self.resolution(parameters);
|
||||||
|
|
||||||
// Convert the view port to the encoded space coordinates
|
// Convert the view port to the encoded space coordinates
|
||||||
@@ -395,14 +351,7 @@ impl SpaceDB {
|
|||||||
let view_port = parameters.view_port(space);
|
let view_port = parameters.view_port(space);
|
||||||
|
|
||||||
// Select the objects
|
// Select the objects
|
||||||
let mut results = self.resolutions[index]
|
let results = self.resolutions[index].find_by_shape(&shape, &view_port)?;
|
||||||
.find_by_shape(&shape, &view_port)?
|
|
||||||
.into_iter()
|
|
||||||
.map(|(position, fields)| (position, fields.clone()))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
// Decode the Value reference
|
|
||||||
self.decode_value(&mut results);
|
|
||||||
|
|
||||||
Ok(results)
|
Ok(results)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user