aboutsummaryrefslogtreecommitdiff
path: root/crates/libanalysis/src/lib.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-13 17:28:34 +0100
committerAleksey Kladov <[email protected]>2018-08-13 17:28:34 +0100
commitd9e86e574ad936f03a64c38dc7b7f39ddcc4eebd (patch)
tree5c262f3209cacc1c67491a0f13d2efd8e4eea311 /crates/libanalysis/src/lib.rs
parent439e0fd32eb943ad7a0be37baf9a19791840ae1e (diff)
Use rayon for parallel indexing
Diffstat (limited to 'crates/libanalysis/src/lib.rs')
-rw-r--r--crates/libanalysis/src/lib.rs36
1 files changed, 34 insertions, 2 deletions
diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 562fab290..ffd81bef8 100644
--- a/crates/libanalysis/src/lib.rs
+++ b/crates/libanalysis/src/lib.rs
@@ -7,15 +7,21 @@ extern crate once_cell;
7extern crate libsyntax2; 7extern crate libsyntax2;
8extern crate libeditor; 8extern crate libeditor;
9extern crate fst; 9extern crate fst;
10extern crate rayon;
10 11
11mod symbol_index; 12mod symbol_index;
12 13
13use once_cell::sync::OnceCell; 14use once_cell::sync::OnceCell;
15use rayon::prelude::*;
14 16
15use std::{ 17use std::{
16 sync::Arc, 18 sync::{
19 Arc,
20 atomic::{AtomicUsize, Ordering::SeqCst},
21 },
17 collections::hash_map::HashMap, 22 collections::hash_map::HashMap,
18 path::{PathBuf, Path}, 23 path::{PathBuf, Path},
24 time::Instant,
19}; 25};
20 26
21use libsyntax2::{ 27use libsyntax2::{
@@ -29,6 +35,7 @@ use self::symbol_index::FileSymbols;
29pub use self::symbol_index::Query; 35pub use self::symbol_index::Query;
30 36
31pub type Result<T> = ::std::result::Result<T, ::failure::Error>; 37pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
38const INDEXING_THRESHOLD: usize = 128;
32 39
33pub struct WorldState { 40pub struct WorldState {
34 data: Arc<WorldData> 41 data: Arc<WorldData>
@@ -56,7 +63,9 @@ impl WorldState {
56 63
57 pub fn change_files(&mut self, changes: impl Iterator<Item=(PathBuf, Option<String>)>) { 64 pub fn change_files(&mut self, changes: impl Iterator<Item=(PathBuf, Option<String>)>) {
58 let data = self.data_mut(); 65 let data = self.data_mut();
66 let mut cnt = 0;
59 for (path, text) in changes { 67 for (path, text) in changes {
68 cnt += 1;
60 data.file_map.remove(&path); 69 data.file_map.remove(&path);
61 if let Some(text) = text { 70 if let Some(text) = text {
62 let file_data = FileData::new(text); 71 let file_data = FileData::new(text);
@@ -65,11 +74,15 @@ impl WorldState {
65 data.file_map.remove(&path); 74 data.file_map.remove(&path);
66 } 75 }
67 } 76 }
77 *data.unindexed.get_mut() += cnt;
68 } 78 }
69 79
70 fn data_mut(&mut self) -> &mut WorldData { 80 fn data_mut(&mut self) -> &mut WorldData {
71 if Arc::get_mut(&mut self.data).is_none() { 81 if Arc::get_mut(&mut self.data).is_none() {
72 self.data = Arc::new(WorldData { 82 self.data = Arc::new(WorldData {
83 unindexed: AtomicUsize::new(
84 self.data.unindexed.load(SeqCst)
85 ),
73 file_map: self.data.file_map.clone(), 86 file_map: self.data.file_map.clone(),
74 }); 87 });
75 } 88 }
@@ -95,10 +108,11 @@ impl World {
95 } 108 }
96 109
97 pub fn world_symbols<'a>(&'a self, mut query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a { 110 pub fn world_symbols<'a>(&'a self, mut query: Query) -> impl Iterator<Item=(&'a Path, &'a FileSymbol)> + 'a {
111 self.reindex();
98 self.data.file_map.iter() 112 self.data.file_map.iter()
99 .flat_map(move |(path, data)| { 113 .flat_map(move |(path, data)| {
100 let path: &'a Path = path.as_path();
101 let symbols = data.symbols(); 114 let symbols = data.symbols();
115 let path: &'a Path = path.as_path();
102 query.process(symbols).into_iter().map(move |s| (path, s)) 116 query.process(symbols).into_iter().map(move |s| (path, s))
103 }) 117 })
104 } 118 }
@@ -129,6 +143,23 @@ impl World {
129 Ok(self.world_symbols(query).collect()) 143 Ok(self.world_symbols(query).collect())
130 } 144 }
131 145
146 fn reindex(&self) {
147 let data = &*self.data;
148 let unindexed = data.unindexed.load(SeqCst);
149 if unindexed < INDEXING_THRESHOLD {
150 return;
151 }
152 if unindexed == data.unindexed.compare_and_swap(unindexed, 0, SeqCst) {
153 let now = Instant::now();
154 data.file_map
155 .par_iter()
156 .for_each(|(_, data)| {
157 data.symbols();
158 });
159 info!("parallel indexing took {:?}", now.elapsed());
160 }
161 }
162
132 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> { 163 fn file_data(&self, path: &Path) -> Result<Arc<FileData>> {
133 match self.data.file_map.get(path) { 164 match self.data.file_map.get(path) {
134 Some(data) => Ok(data.clone()), 165 Some(data) => Ok(data.clone()),
@@ -150,6 +181,7 @@ pub const BREAK: SearchResult = Err(Break);
150 181
151#[derive(Default, Debug)] 182#[derive(Default, Debug)]
152struct WorldData { 183struct WorldData {
184 unindexed: AtomicUsize,
153 file_map: HashMap<PathBuf, Arc<FileData>>, 185 file_map: HashMap<PathBuf, Arc<FileData>>,
154} 186}
155 187