From 72f7cc1569e0ecf3f58c55c9ccb944bde754ec88 Mon Sep 17 00:00:00 2001 From: Paul Masurel Date: Mon, 17 Feb 2020 09:53:38 +0900 Subject: [PATCH] Closes #777 (#779) --- CHANGELOG.md | 1 + src/reader/pool.rs | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a29eda675..c05f14814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Tantivy 0.12.0 - Added backward iteration for `TermDictionary` stream. (@halvorboe) - Fixed a performance issue when searching for the posting lists of a missing term (@audunhalland) - Added a configurable maximum number of docs (10M by default) for a segment to be considered for merge (@hntd187, landed by @halvorboe #713) +- Important Bugfix #777, causing tantivy to retain memory mapping. (diagnosed by @poljar) ## How to update? diff --git a/src/reader/pool.rs b/src/reader/pool.rs index 38b6d92a8..abd5e5a5d 100644 --- a/src/reader/pool.rs +++ b/src/reader/pool.rs @@ -68,7 +68,9 @@ impl Pool { /// After publish, all new `Searcher` acquired will be /// of the new generation. pub fn publish_new_generation(&self, items: Vec) { + assert!(items.len() >= 1); let next_generation = self.next_generation.fetch_add(1, Ordering::SeqCst) + 1; + let num_items = items.len(); for item in items { let gen_item = GenerationItem { item, @@ -77,6 +79,23 @@ impl Pool { self.queue.push(gen_item); } self.advertise_generation(next_generation); + // Purge possible previous searchers. + // + // Assuming at this point no searcher is held more than duration T by the user, + // this guarantees that an obsolete searcher will not be uselessly held (and its associated + // mmap) for more than duration T. + // + // Proof: At this point, obsolete searcher that are held by the user will be held for less + // than T. When released, they will be dropped as their generation is detected obsolete. + // + // We still need to ensure that the searcher that are obsolete and in the pool get removed. + // The queue currently contains up to 2n searchers, in any random order. + // + // Half of them are obsoletes. By requesting `(n+1)` fresh searchers, we ensure that all + // searcher will be inspected. + for _ in 0..(num_items + 1) { + let _ = self.acquire(); + } } /// At the exit of this method,