Skip to content

Commit 7184290

Browse files
committed
VecOfVec optimization
1 parent 72d9727 commit 7184290

2 files changed

Lines changed: 164 additions & 46 deletions

File tree

backend-rust/src/bin/main.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,12 +1009,31 @@ struct Location {
10091009
additional_info: Option<String>,
10101010
}
10111011

1012+
impl Default for Location {
1013+
fn default() -> Self {
1014+
Location {
1015+
name: String::new(),
1016+
center: vec![0.0, 0.0],
1017+
additional_info: None,
1018+
}
1019+
}
1020+
}
1021+
10121022
#[derive(Clone)]
10131023
struct LocationInfo {
10141024
center: Vec<f32>,
10151025
additional_info_ix: usize,
10161026
}
10171027

1028+
impl Default for LocationInfo {
1029+
fn default() -> Self {
1030+
LocationInfo {
1031+
center: vec![0.0, 0.0],
1032+
additional_info_ix: 0,
1033+
}
1034+
}
1035+
}
1036+
10181037
struct SearchLocation {
10191038
pub index: SearchIndex<PrefixTrie<LocationInfo>>,
10201039
pub additional_info: Vec<String>,

backend-rust/src/textsearch.rs

Lines changed: 145 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub struct PrefixTrieBuilder<T> {
99
items: Vec<T>,
1010
}
1111

12-
impl<T: Clone> PrefixTrieBuilder<T> {
12+
impl<T: Clone + Default> PrefixTrieBuilder<T> {
1313
pub fn new() -> Self {
1414
PrefixTrieBuilder {
1515
children: HashMap::new(),
@@ -37,14 +37,61 @@ impl<T: Clone> PrefixTrieBuilder<T> {
3737
total
3838
}
3939

40+
pub fn compute_children_in_order<A>(
41+
&self,
42+
result: &mut Vec<A>,
43+
c: &impl Fn(&PrefixTrieBuilder<T>) -> A,
44+
mut cur_ix: usize,
45+
) {
46+
result[cur_ix] = c(self);
47+
cur_ix += 1;
48+
49+
let mut ch = self
50+
.children
51+
.iter()
52+
.map(|x| {
53+
let t = x.1.total_nodes();
54+
(x.0, x.1, t)
55+
})
56+
.collect::<Vec<_>>();
57+
ch.sort_by_key(|x| (x.2 as isize).wrapping_neg());
58+
59+
for (_, child, _) in ch {
60+
let child_nodes = child.total_nodes();
61+
child.compute_children_in_order(result, c, cur_ix);
62+
cur_ix += child_nodes;
63+
}
64+
}
65+
4066
pub fn finalize(self) -> PrefixTrie<T> {
4167
let total_nodes = self.total_nodes();
4268

69+
let mut num_children_in_order = vec![0; total_nodes];
70+
self.compute_children_in_order(
71+
&mut num_children_in_order,
72+
&|node: &PrefixTrieBuilder<T>| node.children.len(),
73+
0,
74+
);
75+
76+
let mut num_items_in_order = vec![0; total_nodes];
77+
self.compute_children_in_order(
78+
&mut num_items_in_order,
79+
&|node: &PrefixTrieBuilder<T>| node.items.len(),
80+
0,
81+
);
82+
83+
let mut lengths_in_order = vec![0; total_nodes];
84+
self.compute_children_in_order(
85+
&mut lengths_in_order,
86+
&|node: &PrefixTrieBuilder<T>| node.lengths.len(),
87+
0,
88+
);
89+
4390
let mut trie = PrefixTrie {
44-
children: vec![Vec::new(); total_nodes],
91+
children: VecOfVec::new(num_children_in_order),
4592
leafs: vec![false; total_nodes],
46-
items: vec![Vec::new(); total_nodes],
47-
ordered_lengths: vec![vec![]; total_nodes],
93+
items: VecOfVec::new(num_items_in_order),
94+
ordered_lengths: VecOfVec::new(lengths_in_order),
4895
characters: vec!['\0'; total_nodes],
4996
};
5097

@@ -54,13 +101,20 @@ impl<T: Clone> PrefixTrieBuilder<T> {
54101

55102
fn finalize_node(self, trie: &mut PrefixTrie<T>, mut current_ix: IndexType) {
56103
let my_ix = current_ix;
57-
trie.ordered_lengths[my_ix] = {
58-
let mut lengths: Vec<usize> = self.lengths.into_iter().collect();
59-
lengths.sort_unstable();
60-
lengths.into_iter().map(|x| x as LengthType).collect()
61-
};
62-
trie.items[my_ix] = self.items;
63-
trie.leafs[my_ix] = trie.ordered_lengths[my_ix].contains(&0);
104+
105+
let mut lengths: Vec<usize> = self.lengths.into_iter().collect();
106+
lengths.sort_unstable();
107+
108+
let length_ix = trie.ordered_lengths.indices[my_ix];
109+
for (i, l) in lengths.iter().enumerate() {
110+
trie.ordered_lengths.data[length_ix + i] = *l as LengthType;
111+
}
112+
113+
let items_ix = trie.items.indices[my_ix];
114+
for (i, item) in self.items.into_iter().enumerate() {
115+
trie.items.data[items_ix + i] = item;
116+
}
117+
trie.leafs[my_ix] = trie.ordered_lengths.ix(my_ix).any(|x| *x == 0);
64118

65119
current_ix += 1;
66120

@@ -74,8 +128,9 @@ impl<T: Clone> PrefixTrieBuilder<T> {
74128
.collect::<Vec<_>>();
75129
ch.sort_by_key(|x| (x.2 as isize).wrapping_neg());
76130

77-
for (c, child, _) in ch {
78-
trie.children[my_ix].push(current_ix);
131+
let child_ix = trie.children.indices[my_ix];
132+
for (i, (c, child, _)) in ch.into_iter().enumerate() {
133+
trie.children.data[child_ix + i] = current_ix;
79134
trie.characters[current_ix] = c;
80135

81136
let child_nodes = child.total_nodes();
@@ -85,36 +140,84 @@ impl<T: Clone> PrefixTrieBuilder<T> {
85140
}
86141
}
87142

88-
impl<T: Clone> Default for PrefixTrieBuilder<T> {
143+
impl<T: Clone + Default> Default for PrefixTrieBuilder<T> {
89144
fn default() -> Self {
90145
PrefixTrieBuilder::new()
91146
}
92147
}
93148

149+
#[derive(Clone)]
150+
struct VecOfVec<T> {
151+
data: Vec<T>,
152+
indices: Vec<usize>,
153+
}
154+
155+
fn cumsum(lengths: Vec<usize>) -> Vec<usize> {
156+
let mut indices = vec![0; lengths.len() + 1];
157+
let mut sum = 0;
158+
for (i, length) in lengths.iter().enumerate() {
159+
sum += *length;
160+
indices[i + 1] = sum;
161+
}
162+
indices
163+
}
164+
165+
impl<T: Default + Clone> VecOfVec<T> {
166+
fn new(lengths: Vec<usize>) -> Self {
167+
VecOfVec {
168+
data: vec![T::default(); lengths.iter().sum()],
169+
indices: cumsum(lengths),
170+
}
171+
}
172+
173+
fn ix(&self, ix: usize) -> VecOfVecIterator<'_, T> {
174+
VecOfVecIterator {
175+
vec_of_vec: self,
176+
current_ix: self.indices[ix],
177+
end_ix: self.indices[ix + 1],
178+
}
179+
}
180+
}
181+
182+
struct VecOfVecIterator<'a, T> {
183+
vec_of_vec: &'a VecOfVec<T>,
184+
current_ix: usize,
185+
end_ix: usize,
186+
}
187+
188+
impl<'a, T> Iterator for VecOfVecIterator<'a, T> {
189+
type Item = &'a T;
190+
191+
fn next(&mut self) -> Option<Self::Item> {
192+
if self.current_ix < self.end_ix {
193+
let item = &self.vec_of_vec.data[self.current_ix];
194+
self.current_ix += 1;
195+
Some(item)
196+
} else {
197+
None
198+
}
199+
}
200+
}
201+
94202
type IndexType = usize;
95203
type LengthType = u16;
96204
type DistanceType = u8;
97205
type VisitedType = HashMap<(IndexType, usize), DistanceType>;
98206

99207
#[derive(Clone)]
100208
pub struct PrefixTrie<T> {
101-
children: Vec<Vec<IndexType>>,
102-
items: Vec<Vec<T>>,
209+
children: VecOfVec<IndexType>,
210+
items: VecOfVec<T>,
103211
leafs: Vec<bool>,
104212
characters: Vec<char>,
105-
ordered_lengths: Vec<Vec<LengthType>>,
213+
ordered_lengths: VecOfVec<LengthType>,
106214
}
107215

108-
impl<T> PrefixTrie<T> {
216+
impl<T: Clone + Default> PrefixTrie<T> {
109217
pub fn get_child(&self, c: char, ix: IndexType) -> Option<&IndexType> {
110-
self.children[ix].iter().find_map(|child_ix| {
111-
let child_char = &self.characters[*child_ix];
112-
if *child_char == c {
113-
Some(child_ix)
114-
} else {
115-
None
116-
}
117-
})
218+
self.children
219+
.ix(ix)
220+
.find(|child_ix| self.characters[**child_ix] == c)
118221
}
119222

120223
pub fn search(&self, word: &str) -> bool {
@@ -133,7 +236,7 @@ impl<T> PrefixTrie<T> {
133236
&'a self,
134237
prefix: &'a str,
135238
ix: IndexType,
136-
) -> Box<dyn Iterator<Item = (String, &T)> + 'a> {
239+
) -> Box<dyn Iterator<Item = (String, &'a T)> + 'a> {
137240
let mut current_ix = ix;
138241
for c in prefix.chars() {
139242
match self.get_child(c, current_ix) {
@@ -143,8 +246,8 @@ impl<T> PrefixTrie<T> {
143246
}
144247

145248
Box::new(
146-
self.ordered_lengths[current_ix]
147-
.iter()
249+
self.ordered_lengths
250+
.ix(current_ix)
148251
.flat_map(move |&x| self.childs_of_lengths(current_ix, x))
149252
.map(move |(suffix, item)| {
150253
let mut full = String::new();
@@ -160,15 +263,15 @@ impl<T> PrefixTrie<T> {
160263
ix: IndexType,
161264
length: LengthType,
162265
) -> Box<dyn Iterator<Item = (String, &T)> + '_> {
163-
if !self.ordered_lengths[ix].contains(&length) {
266+
if !self.ordered_lengths.ix(ix).any(|x| *x == length) {
164267
return Box::new(std::iter::empty());
165268
}
166269

167270
if length == 0 {
168-
return Box::new(self.items[ix].iter().map(|item| (String::new(), item)));
271+
return Box::new(self.items.ix(ix).map(|item| (String::new(), item)));
169272
}
170273

171-
Box::new(self.children[ix].iter().flat_map(move |child_ix| {
274+
Box::new(self.children.ix(ix).flat_map(move |child_ix| {
172275
let suffixes = self.childs_of_lengths(*child_ix, length - 1);
173276
suffixes.map(move |(suffix, item)| {
174277
let mut s = String::new();
@@ -223,7 +326,7 @@ pub struct PrefixTrieMaxDistanceIterator<'a, T> {
223326
word: Vec<char>,
224327
}
225328

226-
impl<'a, T> Iterator for PrefixTrieMaxDistanceIterator<'a, T> {
329+
impl<'a, T: Clone + Default> Iterator for PrefixTrieMaxDistanceIterator<'a, T> {
227330
type Item = Box<dyn Iterator<Item = (String, &'a T)> + 'a>;
228331

229332
fn next(&mut self) -> Option<Self::Item> {
@@ -261,7 +364,7 @@ pub struct PrefixTrieExactDistanceIterator<'a, T> {
261364
word: Vec<char>,
262365
}
263366

264-
impl<'a, T> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
367+
impl<'a, T: Clone + Default> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
265368
type Item = Box<dyn Iterator<Item = (String, &'a T)> + 'a>;
266369

267370
fn next(&mut self) -> Option<Self::Item> {
@@ -282,15 +385,11 @@ impl<'a, T> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
282385
if distance == 0 && (word_ix == self.word.len()) && self.trie.leafs[node] {
283386
if self.continuations {
284387
to_return = Some(Box::new(
285-
self.trie.items[node]
286-
.iter()
287-
.map(move |item| (p.clone(), item)),
388+
self.trie.items.ix(node).map(move |item| (p.clone(), item)),
288389
));
289390
} else {
290391
return Some(Box::new(
291-
self.trie.items[node]
292-
.iter()
293-
.map(move |item| (p.clone(), item)),
392+
self.trie.items.ix(node).map(move |item| (p.clone(), item)),
294393
));
295394
}
296395
}
@@ -310,7 +409,7 @@ impl<'a, T> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
310409
continue;
311410
}
312411

313-
for child in self.trie.children[node].iter() {
412+
for child in self.trie.children.ix(node) {
314413
// Substitution
315414
let character = self.trie.characters[*child];
316415
if character != c {
@@ -327,7 +426,7 @@ impl<'a, T> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
327426
.push((node, word_ix + 1, distance - 1, prefix.clone()));
328427

329428
// Insertion
330-
for child in self.trie.children[node].iter() {
429+
for child in self.trie.children.ix(node) {
331430
let character = self.trie.characters[*child];
332431
if character != c {
333432
self.stack.push((*child, word_ix, distance - 1, {
@@ -350,7 +449,7 @@ impl<'a, T> Iterator for PrefixTrieExactDistanceIterator<'a, T> {
350449
if distance == 0 && !self.continuations {
351450
continue;
352451
}
353-
for child in self.trie.children[node].iter() {
452+
for child in self.trie.children.ix(node) {
354453
let character = self.trie.characters[*child];
355454
self.stack.push((
356455
*child,
@@ -378,13 +477,13 @@ pub struct SearchIndex<TrieType> {
378477
trie: TrieType,
379478
}
380479

381-
impl<T: Clone> Default for SearchIndex<PrefixTrieBuilder<T>> {
480+
impl<T: Clone + Default> Default for SearchIndex<PrefixTrieBuilder<T>> {
382481
fn default() -> Self {
383482
SearchIndex::new()
384483
}
385484
}
386485

387-
impl<T: Clone> SearchIndex<PrefixTrieBuilder<T>> {
486+
impl<T: Clone + Default> SearchIndex<PrefixTrieBuilder<T>> {
388487
pub fn new() -> Self {
389488
SearchIndex {
390489
trie: PrefixTrieBuilder::new(),
@@ -402,7 +501,7 @@ impl<T: Clone> SearchIndex<PrefixTrieBuilder<T>> {
402501
}
403502
}
404503

405-
impl<T: Clone> SearchIndex<PrefixTrie<T>> {
504+
impl<T: Clone + Default> SearchIndex<PrefixTrie<T>> {
406505
pub fn continuations<'a>(&'a self, prefix: &'a str) -> Box<dyn Iterator<Item = &'a T> + 'a> {
407506
Box::new(self.trie.continuations(prefix, 0).map(|x| x.1))
408507
}

0 commit comments

Comments
 (0)