Mercurial > public > mercurial-scm > hg
diff rust/hg-cpython/src/revlog.rs @ 51394:b01e7d97e167
revlog: add a Rust implementation of `headrevsdiff`
Python implementation of `headrevsdiff` can be very slow in the worst
case compared with the `heads` computation it replaces, since the
latter is done in Rust.
Even the average case of this Python implementation is still
noticeable in the profiles.
This patch makes the computation much much faster by doing it in Rust.
author | Arseniy Alekseyev <aalekseyev@janestreet.com> |
---|---|
date | Mon, 12 Feb 2024 20:01:27 +0000 |
parents | 5b4995b40db0 |
children | f8bf1a8e9181 |
line wrap: on
line diff
--- a/rust/hg-cpython/src/revlog.rs Thu Dec 21 20:30:03 2023 +0000 +++ b/rust/hg-cpython/src/revlog.rs Mon Feb 12 20:01:27 2024 +0000 @@ -315,6 +315,15 @@ Ok(rust_res) } + /// get diff in head revisions + def headrevsdiff(&self, *args, **_kw) -> PyResult<PyObject> { + let rust_res = self.inner_headrevsdiff( + py, + &args.get_item(py, 0), + &args.get_item(py, 1))?; + Ok(rust_res) + } + /// get filtered head revisions def headrevsfiltered(&self, *args, **_kw) -> PyResult<PyObject> { let rust_res = self.inner_headrevsfiltered(py, &args.get_item(py, 0))?; @@ -827,6 +836,38 @@ .into_object()) } + fn check_revision( + index: &hg::index::Index, + rev: UncheckedRevision, + py: Python, + ) -> PyResult<Revision> { + index + .check_revision(rev) + .ok_or_else(|| rev_not_in_index(py, rev)) + } + + fn inner_headrevsdiff( + &self, + py: Python, + begin: &PyObject, + end: &PyObject, + ) -> PyResult<PyObject> { + let begin = begin.extract::<BaseRevision>(py)?; + let end = end.extract::<BaseRevision>(py)?; + let index = &mut *self.index(py).borrow_mut(); + let begin = + Self::check_revision(index, UncheckedRevision(begin - 1), py)?; + let end = Self::check_revision(index, UncheckedRevision(end - 1), py)?; + let (removed, added) = index + .head_revs_diff(begin, end) + .map_err(|e| graph_error(py, e))?; + let removed: Vec<_> = + removed.into_iter().map(PyRevision::from).collect(); + let added: Vec<_> = added.into_iter().map(PyRevision::from).collect(); + let res = (removed, added).to_py_object(py).into_object(); + Ok(res) + } + fn inner_headrevsfiltered( &self, py: Python,