comparison rust/hg-cpython/src/revlog.rs @ 52180:1032bb0ef365

rust-revlog: build an in-memory nodemap if a given revlog gets queried a lot This will help with non-persistent nodemap repos that would benefit from one, and mirrors what the C implementation does.
author Raphaël Gomès <rgomes@octobus.net>
date Wed, 31 Jul 2024 15:41:08 +0200
parents c90e0f65896e
children bd8081e9fd62
comparison
equal deleted inserted replaced
52179:c90e0f65896e 52180:1032bb0ef365
41 NULL_REVISION, 41 NULL_REVISION,
42 }; 42 };
43 use std::{ 43 use std::{
44 cell::{Cell, RefCell}, 44 cell::{Cell, RefCell},
45 collections::{HashMap, HashSet}, 45 collections::{HashMap, HashSet},
46 sync::atomic::{AtomicBool, Ordering}, 46 sync::atomic::{AtomicBool, AtomicUsize, Ordering},
47 sync::OnceLock, 47 sync::OnceLock,
48 }; 48 };
49 use vcsgraph::graph::Graph as VCSGraph; 49 use vcsgraph::graph::Graph as VCSGraph;
50 50
51 pub struct PySharedIndex { 51 pub struct PySharedIndex {
721 data index_mmap: RefCell<PyBuffer>; 721 data index_mmap: RefCell<PyBuffer>;
722 data head_revs_py_list: RefCell<Option<PyList>>; 722 data head_revs_py_list: RefCell<Option<PyList>>;
723 data head_node_ids_py_list: RefCell<Option<PyList>>; 723 data head_node_ids_py_list: RefCell<Option<PyList>>;
724 data revision_cache: RefCell<Option<PyObject>>; 724 data revision_cache: RefCell<Option<PyObject>>;
725 data use_persistent_nodemap: bool; 725 data use_persistent_nodemap: bool;
726 data nodemap_queries: AtomicUsize;
726 727
727 def __new__( 728 def __new__(
728 _cls, 729 _cls,
729 vfs_base: PyObject, 730 vfs_base: PyObject,
730 fncache: PyObject, 731 fncache: PyObject,
764 765
765 def clear_cache(&self) -> PyResult<PyObject> { 766 def clear_cache(&self) -> PyResult<PyObject> {
766 assert!(!self.is_delaying(py)?); 767 assert!(!self.is_delaying(py)?);
767 self.revision_cache(py).borrow_mut().take(); 768 self.revision_cache(py).borrow_mut().take();
768 self.inner(py).borrow_mut().clear_cache(); 769 self.inner(py).borrow_mut().clear_cache();
770 self.nodemap_queries(py).store(0, Ordering::Relaxed);
769 Ok(py.None()) 771 Ok(py.None())
770 } 772 }
771 773
772 @property def canonical_index_file(&self) -> PyResult<PyBytes> { 774 @property def canonical_index_file(&self) -> PyResult<PyBytes> {
773 let path = self.inner(py).borrow().canonical_index_file(); 775 let path = self.inner(py).borrow().canonical_index_file();
1113 let node = node_from_py_bytes(py, &node)?; 1115 let node = node_from_py_bytes(py, &node)?;
1114 // Filelogs have no persistent nodemaps and are often small, use a 1116 // Filelogs have no persistent nodemaps and are often small, use a
1115 // brute force lookup from the end backwards. If there is a very large 1117 // brute force lookup from the end backwards. If there is a very large
1116 // filelog (automation file that changes every commit etc.), it also 1118 // filelog (automation file that changes every commit etc.), it also
1117 // seems to work quite well for all measured purposes so far. 1119 // seems to work quite well for all measured purposes so far.
1118 // 1120 let mut nodemap_queries =
1119 // TODO build an in-memory nodemap if more than 4 queries to the same 1121 self.nodemap_queries(py).fetch_add(1, Ordering::Relaxed);
1120 // revlog are made? 1122 // Still need to add since `fetch_add` returns the old value
1121 if !*self.use_persistent_nodemap(py) { 1123 nodemap_queries += 1;
1124 if !*self.use_persistent_nodemap(py) && nodemap_queries <= 4 {
1122 let idx = &self.inner(py).borrow().index; 1125 let idx = &self.inner(py).borrow().index;
1123 let res = 1126 let res =
1124 idx.rev_from_node_no_persistent_nodemap(node.into()).ok(); 1127 idx.rev_from_node_no_persistent_nodemap(node.into()).ok();
1125 return Ok(res.map(Into::into)) 1128 return Ok(res.map(Into::into))
1126 } 1129 }
2023 RefCell::new(buf), 2026 RefCell::new(buf),
2024 RefCell::new(None), 2027 RefCell::new(None),
2025 RefCell::new(None), 2028 RefCell::new(None),
2026 RefCell::new(None), 2029 RefCell::new(None),
2027 use_persistent_nodemap, 2030 use_persistent_nodemap,
2031 AtomicUsize::new(0),
2028 ) 2032 )
2029 } 2033 }
2030 } 2034 }
2031 2035
2032 py_class!(pub class NodeTree |py| { 2036 py_class!(pub class NodeTree |py| {