From 700335e6ab610e323095e00a90cc0428faf6679f Mon Sep 17 00:00:00 2001 From: Christian Schilling Date: Tue, 23 Aug 2022 20:39:09 +0200 Subject: [PATCH] Speed up history queries History queries where very slow because `find_original(...)` is executed on every commit. The idea of this optimisation is reduce the amount of history to traverse with each commit visited, taking advantage of the topological order of the traversal. Change-Id: history-query-optimisation --- src/graphql.rs | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/graphql.rs b/src/graphql.rs index 390d92d5d..faa0dc9d9 100644 --- a/src/graphql.rs +++ b/src/graphql.rs @@ -79,6 +79,7 @@ impl Revision { } fn hash(&self, context: &Context) -> FieldResult { + rs_tracing::trace_scoped!("hash"); let transaction = context.transaction.lock()?; let commit = transaction.repo().find_commit(self.commit_id)?; let filter_commit = filter::apply_to_commit(self.filter, &commit, &transaction)?; @@ -169,6 +170,7 @@ impl Revision { offset: Option, context: &Context, ) -> FieldResult> { + rs_tracing::trace_scoped!("history"); let limit = limit.unwrap_or(1) as usize; let offset = offset.unwrap_or(0) as usize; let transaction = context.transaction.lock()?; @@ -184,18 +186,33 @@ impl Revision { walk.set_sorting(git2::Sort::TOPOLOGICAL)?; walk.push(filter_commit.id())?; - Ok(walk - .skip(offset) - .take(limit) + let mut contained_in = self.commit_id; + let mut ids = { + rs_tracing::trace_scoped!("walk"); + walk.skip(offset) + .take(limit) + .map(|id| id.unwrap_or(git2::Oid::zero())) + .collect::>() + }; + + { + rs_tracing::trace_scoped!("walk"); + for i in 0..ids.len() { + ids[i] = history::find_original(&transaction, self.filter, contained_in, ids[i])?; + contained_in = transaction + .repo() + .find_commit(ids[i])? + .parent_ids() + .next() + .unwrap_or(ids[i]); + } + } + + Ok(ids + .into_iter() .map(|id| Revision { filter: self.filter, - commit_id: history::find_original( - &transaction, - self.filter, - self.commit_id, - id.unwrap_or(git2::Oid::zero()), - ) - .unwrap_or(git2::Oid::zero()), + commit_id: id, }) .collect()) }