comparison rust/hg-cpython/src/revlog.rs @ 51258:9088c6d65ef6

rust-index-cpython: cache the heads' PyList representation This is the same optimization that the C index does, we just have more separation of the Python and native sides.
author Rapha?l Gom?s <rgomes@octobus.net>
date Wed, 29 Nov 2023 23:22:51 -0500
parents 8b89f7cc953a
children f20c4b307a5a
comparison
equal deleted inserted replaced
51257:c4f1a790bda8 51258:9088c6d65ef6
94 data docket: RefCell<Option<PyObject>>; 94 data docket: RefCell<Option<PyObject>>;
95 // Holds a reference to the mmap'ed persistent nodemap data 95 // Holds a reference to the mmap'ed persistent nodemap data
96 data nodemap_mmap: RefCell<Option<PyBuffer>>; 96 data nodemap_mmap: RefCell<Option<PyBuffer>>;
97 // Holds a reference to the mmap'ed persistent index data 97 // Holds a reference to the mmap'ed persistent index data
98 data index_mmap: RefCell<Option<PyBuffer>>; 98 data index_mmap: RefCell<Option<PyBuffer>>;
99 data head_revs_py_list: RefCell<Option<PyList>>;
99 100
100 def __new__( 101 def __new__(
101 _cls, 102 _cls,
102 data: PyObject, 103 data: PyObject,
103 default_header: u32, 104 default_header: u32,
255 /// It is Python's responsibility to call `update_nodemap_data` again. 256 /// It is Python's responsibility to call `update_nodemap_data` again.
256 def clearcaches(&self) -> PyResult<PyObject> { 257 def clearcaches(&self) -> PyResult<PyObject> {
257 self.nt(py).borrow_mut().take(); 258 self.nt(py).borrow_mut().take();
258 self.docket(py).borrow_mut().take(); 259 self.docket(py).borrow_mut().take();
259 self.nodemap_mmap(py).borrow_mut().take(); 260 self.nodemap_mmap(py).borrow_mut().take();
261 self.head_revs_py_list(py).borrow_mut().take();
260 self.index(py).borrow().clear_caches(); 262 self.index(py).borrow().clear_caches();
261 Ok(py.None()) 263 Ok(py.None())
262 } 264 }
263 265
264 /// return the raw binary string representing a revision 266 /// return the raw binary string representing a revision
619 })?, 621 })?,
620 RefCell::new(None), 622 RefCell::new(None),
621 RefCell::new(None), 623 RefCell::new(None),
622 RefCell::new(None), 624 RefCell::new(None),
623 RefCell::new(Some(buf)), 625 RefCell::new(Some(buf)),
626 RefCell::new(None),
624 ) 627 )
625 } 628 }
626 629
627 fn len(&self, py: Python) -> PyResult<usize> { 630 fn len(&self, py: Python) -> PyResult<usize> {
628 let rust_index_len = self.index(py).borrow().len(); 631 let rust_index_len = self.index(py).borrow().len();
771 }) 774 })
772 } 775 }
773 776
774 fn inner_headrevs(&self, py: Python) -> PyResult<PyObject> { 777 fn inner_headrevs(&self, py: Python) -> PyResult<PyObject> {
775 let index = &*self.index(py).borrow(); 778 let index = &*self.index(py).borrow();
776 let as_vec: Vec<PyObject> = index 779 if let Some(new_heads) =
777 .head_revs() 780 index.head_revs_shortcut().map_err(|e| graph_error(py, e))?
778 .map_err(|e| graph_error(py, e))? 781 {
779 .iter() 782 self.cache_new_heads_py_list(new_heads, py);
780 .map(|r| PyRevision::from(*r).into_py_object(py).into_object()) 783 }
781 .collect(); 784
782 Ok(PyList::new(py, &as_vec).into_object()) 785 Ok(self
786 .head_revs_py_list(py)
787 .borrow()
788 .as_ref()
789 .expect("head revs should be cached")
790 .clone_ref(py)
791 .into_object())
783 } 792 }
784 793
785 fn inner_headrevsfiltered( 794 fn inner_headrevsfiltered(
786 &self, 795 &self,
787 py: Python, 796 py: Python,
788 filtered_revs: &PyObject, 797 filtered_revs: &PyObject,
789 ) -> PyResult<PyObject> { 798 ) -> PyResult<PyObject> {
790 let index = &mut *self.index(py).borrow_mut(); 799 let index = &mut *self.index(py).borrow_mut();
791 let filtered_revs = rev_pyiter_collect(py, filtered_revs, index)?; 800 let filtered_revs = rev_pyiter_collect(py, filtered_revs, index)?;
792 801
793 let as_vec: Vec<PyObject> = index 802 if let Some(new_heads) = index
794 .head_revs_filtered(&filtered_revs) 803 .head_revs_filtered(&filtered_revs, true)
795 .map_err(|e| graph_error(py, e))? 804 .map_err(|e| graph_error(py, e))?
805 {
806 self.cache_new_heads_py_list(new_heads, py);
807 }
808
809 Ok(self
810 .head_revs_py_list(py)
811 .borrow()
812 .as_ref()
813 .expect("head revs should be cached")
814 .clone_ref(py)
815 .into_object())
816 }
817
818 fn cache_new_heads_py_list(
819 &self,
820 new_heads: Vec<Revision>,
821 py: Python<'_>,
822 ) -> PyList {
823 let as_vec: Vec<PyObject> = new_heads
796 .iter() 824 .iter()
797 .map(|r| PyRevision::from(*r).into_py_object(py).into_object()) 825 .map(|r| PyRevision::from(*r).into_py_object(py).into_object())
798 .collect(); 826 .collect();
799 Ok(PyList::new(py, &as_vec).into_object()) 827 let new_heads_py_list = PyList::new(py, &as_vec);
828 *self.head_revs_py_list(py).borrow_mut() =
829 Some(new_heads_py_list.clone_ref(py));
830 new_heads_py_list
800 } 831 }
801 832
802 fn inner_ancestors( 833 fn inner_ancestors(
803 &self, 834 &self,
804 py: Python, 835 py: Python,