Mercurial > hg
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| { |