use std::sync::{
Arc,
atomic::{AtomicUsize, Ordering},
};
#[derive(Default)]
struct Counts {
filter_evaluations: AtomicUsize,
filter_rows: AtomicUsize,
eligibility_intersections: AtomicUsize,
scorers: AtomicUsize,
frequencies: AtomicUsize,
expansions: AtomicUsize,
structured_retained_rows: AtomicUsize,
structured_bound_terms: AtomicUsize,
corpus_statistics: AtomicUsize,
live_statistics_rows: AtomicUsize,
live_df_walks: AtomicUsize,
live_df_docids: AtomicUsize,
live_df_blocks: AtomicUsize,
phrase_reanalyses: AtomicUsize,
phrase_text_bytes: AtomicUsize,
phrase_positions: AtomicUsize,
phrase_position_bytes: AtomicUsize,
vocabulary_builds: AtomicUsize,
vocabulary_copied_bytes: AtomicUsize,
vocabulary_terms_visited: AtomicUsize,
vocabulary_seek_steps: AtomicUsize,
vocabulary_group_checks: AtomicUsize,
fuzzy_candidates: AtomicUsize,
fuzzy_dp_cells: AtomicUsize,
fuzzy_row_allocations: AtomicUsize,
fuzzy_scratch_constructions: AtomicUsize,
phonetic_encodings: AtomicUsize,
phonetic_builds: AtomicUsize,
phonetic_bucket_terms: AtomicUsize,
}
pub fn filter_work() -> (usize, usize, usize) {
CURRENT.with(|current| {
current.borrow().as_ref().map_or((0, 0, 0), |o| {
(
o.0.filter_evaluations.load(Ordering::Relaxed),
o.0.filter_rows.load(Ordering::Relaxed),
o.0.eligibility_intersections.load(Ordering::Relaxed),
)
})
})
}
pub(crate) fn record_filter_work(evaluations: usize, rows: usize, intersections: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.filter_evaluations
.fetch_add(evaluations, Ordering::Relaxed);
o.0.filter_rows.fetch_add(rows, Ordering::Relaxed);
o.0.eligibility_intersections
.fetch_add(intersections, Ordering::Relaxed);
}
});
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct VocabularyWork {
pub builds: usize,
pub copied_bytes: usize,
pub terms_visited: usize,
pub seek_steps: usize,
}
pub fn vocabulary_work() -> VocabularyWork {
CURRENT.with(|current| {
current
.borrow()
.as_ref()
.map_or(VocabularyWork::default(), |o| VocabularyWork {
builds: o.0.vocabulary_builds.load(Ordering::Relaxed),
copied_bytes: o.0.vocabulary_copied_bytes.load(Ordering::Relaxed),
terms_visited: o.0.vocabulary_terms_visited.load(Ordering::Relaxed),
seek_steps: o.0.vocabulary_seek_steps.load(Ordering::Relaxed),
})
})
}
pub(crate) fn vocabulary_build(bytes: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.vocabulary_builds.fetch_add(1, Ordering::Relaxed);
o.0.vocabulary_copied_bytes
.fetch_add(bytes, Ordering::Relaxed);
}
});
}
pub(crate) fn vocabulary_visit() {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.vocabulary_terms_visited.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn vocabulary_seek() {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.vocabulary_seek_steps.fetch_add(1, Ordering::Relaxed);
}
});
}
pub fn vocabulary_group_checks() -> usize {
CURRENT.with(|current| {
current
.borrow()
.as_ref()
.map_or(0, |o| o.0.vocabulary_group_checks.load(Ordering::Relaxed))
})
}
pub(crate) fn record_vocabulary_group_checks(count: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.vocabulary_group_checks
.fetch_add(count, Ordering::Relaxed);
}
});
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct FuzzyWork {
pub candidates: usize,
pub dp_cells: usize,
pub row_allocations: usize,
pub scratch_constructions: usize,
}
pub fn fuzzy_work() -> FuzzyWork {
CURRENT.with(|current| {
current
.borrow()
.as_ref()
.map_or(FuzzyWork::default(), |o| FuzzyWork {
candidates: o.0.fuzzy_candidates.load(Ordering::Relaxed),
dp_cells: o.0.fuzzy_dp_cells.load(Ordering::Relaxed),
row_allocations: o.0.fuzzy_row_allocations.load(Ordering::Relaxed),
scratch_constructions: o.0.fuzzy_scratch_constructions.load(Ordering::Relaxed),
})
})
}
pub(crate) fn fuzzy_scratch() {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.fuzzy_scratch_constructions
.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn fuzzy_distance(cells: usize, allocations: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.fuzzy_candidates.fetch_add(1, Ordering::Relaxed);
o.0.fuzzy_dp_cells.fetch_add(cells, Ordering::Relaxed);
o.0.fuzzy_row_allocations
.fetch_add(allocations, Ordering::Relaxed);
}
});
}
pub fn phonetic_encoding_calls() -> usize {
CURRENT.with(|current| {
current
.borrow()
.as_ref()
.map_or(0, |o| o.0.phonetic_encodings.load(Ordering::Relaxed))
})
}
pub(crate) fn phonetic_encoding() {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.phonetic_encodings.fetch_add(1, Ordering::Relaxed);
}
});
}
pub fn phonetic_index_work() -> (usize, usize) {
CURRENT.with(|current| {
current.borrow().as_ref().map_or((0, 0), |o| {
(
o.0.phonetic_builds.load(Ordering::Relaxed),
o.0.phonetic_bucket_terms.load(Ordering::Relaxed),
)
})
})
}
pub(crate) fn phonetic_index_build() {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.phonetic_builds.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn phonetic_bucket(count: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.phonetic_bucket_terms
.fetch_add(count, Ordering::Relaxed);
}
});
}
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
pub struct LiveDfWork {
pub walks: usize,
pub docids: usize,
pub blocks: usize,
}
pub fn live_df_work() -> LiveDfWork {
CURRENT.with(|current| {
current
.borrow()
.as_ref()
.map_or(LiveDfWork::default(), |o| LiveDfWork {
walks: o.0.live_df_walks.load(Ordering::Relaxed),
docids: o.0.live_df_docids.load(Ordering::Relaxed),
blocks: o.0.live_df_blocks.load(Ordering::Relaxed),
})
})
}
pub(crate) fn live_df_walk(docids: usize, blocks: usize) {
CURRENT.with(|current| {
if let Some(o) = current.borrow().as_ref() {
o.0.live_df_walks.fetch_add(1, Ordering::Relaxed);
o.0.live_df_docids.fetch_add(docids, Ordering::Relaxed);
o.0.live_df_blocks.fetch_add(blocks, Ordering::Relaxed);
}
});
}
pub fn live_statistics_rows() -> usize {
CURRENT.with(|current| {
current.borrow().as_ref().map_or(0, |observer| {
observer.0.live_statistics_rows.load(Ordering::Relaxed)
})
})
}
pub(crate) fn live_statistics_row() {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer
.0
.live_statistics_rows
.fetch_add(1, Ordering::Relaxed);
}
});
}
#[derive(Clone, Default)]
pub struct Observer(Arc<Counts>);
thread_local! {
static CURRENT: std::cell::RefCell<Option<Observer>> = const { std::cell::RefCell::new(None) };
}
pub fn begin() {
CURRENT.with(|current| *current.borrow_mut() = Some(Observer::default()));
}
pub fn take() -> (usize, usize) {
let (scorers, frequencies, _) = take_with_expansions();
(scorers, frequencies)
}
pub fn take_with_expansions() -> (usize, usize, usize) {
let (scorers, frequencies, expansions, _) = take_with_collection();
(scorers, frequencies, expansions)
}
pub fn take_with_collection() -> (usize, usize, usize, usize) {
let (scorers, frequencies, expansions, retained, _) = take_with_bounds();
(scorers, frequencies, expansions, retained)
}
pub fn take_with_bounds() -> (usize, usize, usize, usize, usize) {
CURRENT.with(|current| {
current.take().map_or((0, 0, 0, 0, 0), |observer| {
(
observer.0.scorers.load(Ordering::Relaxed),
observer.0.frequencies.load(Ordering::Relaxed),
observer.0.expansions.load(Ordering::Relaxed),
observer.0.structured_retained_rows.load(Ordering::Relaxed),
observer.0.structured_bound_terms.load(Ordering::Relaxed),
)
})
})
}
pub(crate) fn structured_bounds(terms: usize) {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer
.0
.structured_bound_terms
.fetch_add(terms, Ordering::Relaxed);
}
});
}
pub fn corpus_statistics_calls() -> usize {
CURRENT.with(|current| {
current.borrow().as_ref().map_or(0, |observer| {
observer.0.corpus_statistics.load(Ordering::Relaxed)
})
})
}
pub fn phrase_reanalysis_work() -> (usize, usize) {
CURRENT.with(|current| {
current.borrow().as_ref().map_or((0, 0), |observer| {
(
observer.0.phrase_reanalyses.load(Ordering::Relaxed),
observer.0.phrase_text_bytes.load(Ordering::Relaxed),
)
})
})
}
#[cfg(test)]
pub(crate) fn phrase_reanalysis(bytes: usize) {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer.0.phrase_reanalyses.fetch_add(1, Ordering::Relaxed);
observer
.0
.phrase_text_bytes
.fetch_add(bytes, Ordering::Relaxed);
}
});
}
pub fn phrase_position_work() -> (usize, usize) {
CURRENT.with(|current| {
current.borrow().as_ref().map_or((0, 0), |observer| {
(
observer.0.phrase_positions.load(Ordering::Relaxed),
observer.0.phrase_position_bytes.load(Ordering::Relaxed),
)
})
})
}
pub(crate) fn phrase_positions(positions: usize, bytes: usize) {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer
.0
.phrase_positions
.fetch_add(positions, Ordering::Relaxed);
observer
.0
.phrase_position_bytes
.fetch_add(bytes, Ordering::Relaxed);
}
});
}
pub(crate) fn corpus_statistics() {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer.0.corpus_statistics.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn structured_collection(rows: usize) {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer
.0
.structured_retained_rows
.fetch_max(rows, Ordering::Relaxed);
}
});
}
pub(crate) fn current() -> Option<Observer> {
CURRENT.with(|current| current.borrow().clone())
}
pub(crate) struct Scope(Option<Observer>);
impl Drop for Scope {
fn drop(&mut self) {
CURRENT.with(|current| *current.borrow_mut() = self.0.take());
}
}
pub(crate) fn enter(observer: Option<Observer>) -> Scope {
Scope(CURRENT.with(|current| current.replace(observer)))
}
pub(crate) fn scorer() {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer.0.scorers.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn frequency() {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer.0.frequencies.fetch_add(1, Ordering::Relaxed);
}
});
}
pub(crate) fn expansion() {
CURRENT.with(|current| {
if let Some(observer) = current.borrow().as_ref() {
observer.0.expansions.fetch_add(1, Ordering::Relaxed);
}
});
}