comparison rust/hg-cpython/src/revlog.rs @ 51226:1b23aaf5eb7b

rust-index: optimize find_gca_candidates() on less than 8 revisions This is expected to be by far the most common case, given that, e.g., merging involves using it on two revisions. Using a `u8` as support for the bitset obviously divides the amount of RAM needed by 8. To state the obvious, on a repository with 10 million changesets, this spares 70MB. It is also possible that it'd be slightly faster, because it is easier to allocate and provides better cache locality. It is possible that some exhaustive listing of the traits implemented by `u8` and `u64` would avoid the added duplication, but that can be done later and would need a replacement for the `MAX` consts.
author Georges Racinet <georges.racinet@octobus.net>
date Fri, 20 Oct 2023 09:12:22 +0200
parents 89ce6a49bfeb
children 5807e3a8865e
comparison
equal deleted inserted replaced
51225:61a6ef876efd 51226:1b23aaf5eb7b
18 PyModule, PyObject, PyResult, PySet, PyString, PyTuple, Python, 18 PyModule, PyObject, PyResult, PySet, PyString, PyTuple, Python,
19 PythonObject, ToPyObject, 19 PythonObject, ToPyObject,
20 }; 20 };
21 use hg::{ 21 use hg::{
22 errors::HgError, 22 errors::HgError,
23 index::{IndexHeader, Phase, RevisionDataParams, SnapshotsCache}, 23 index::{
24 IndexHeader, Phase, RevisionDataParams, SnapshotsCache,
25 INDEX_ENTRY_SIZE,
26 },
24 nodemap::{Block, NodeMapError, NodeTree}, 27 nodemap::{Block, NodeMapError, NodeTree},
25 revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex}, 28 revlog::{nodemap::NodeMap, NodePrefix, RevlogError, RevlogIndex},
26 BaseRevision, Revision, UncheckedRevision, NULL_REVISION, 29 BaseRevision, Revision, UncheckedRevision, NULL_REVISION,
27 }; 30 };
28 use std::{cell::RefCell, collections::HashMap}; 31 use std::{cell::RefCell, collections::HashMap};
481 self.inner_update_nodemap_data(py, docket, nm_data) 484 self.inner_update_nodemap_data(py, docket, nm_data)
482 } 485 }
483 486
484 @property 487 @property
485 def entry_size(&self) -> PyResult<PyInt> { 488 def entry_size(&self) -> PyResult<PyInt> {
486 self.cindex(py).borrow().inner().getattr(py, "entry_size")?.extract::<PyInt>(py) 489 let rust_res: PyInt = INDEX_ENTRY_SIZE.to_py_object(py);
490
491 let c_res = self.cindex(py).borrow().inner()
492 .getattr(py, "entry_size")?;
493 assert_py_eq(py, "entry_size", rust_res.as_object(), &c_res)?;
494
495 Ok(rust_res)
487 } 496 }
488 497
489 @property 498 @property
490 def rust_ext_compat(&self) -> PyResult<PyInt> { 499 def rust_ext_compat(&self) -> PyResult<PyInt> {
491 self.cindex(py).borrow().inner().getattr(py, "rust_ext_compat")?.extract::<PyInt>(py) 500 // will be entirely removed when the Rust index yet useful to
501 // implement in Rust to detangle things when removing `self.cindex`
502 let rust_res: PyInt = 1.to_py_object(py);
503
504 let c_res = self.cindex(py).borrow().inner()
505 .getattr(py, "rust_ext_compat")?;
506 assert_py_eq(py, "rust_ext_compat", rust_res.as_object(), &c_res)?;
507
508 Ok(rust_res)
492 } 509 }
493 510
494 }); 511 });
495 512
496 /// Take a (potentially) mmap'ed buffer, and return the underlying Python 513 /// Take a (potentially) mmap'ed buffer, and return the underlying Python
669 686
670 fn len(&self, py: Python) -> PyResult<usize> { 687 fn len(&self, py: Python) -> PyResult<usize> {
671 let rust_index_len = self.index(py).borrow().len(); 688 let rust_index_len = self.index(py).borrow().len();
672 let cindex_len = self.cindex(py).borrow().inner().len(py)?; 689 let cindex_len = self.cindex(py).borrow().inner().len(py)?;
673 assert_eq!(rust_index_len, cindex_len); 690 assert_eq!(rust_index_len, cindex_len);
674 Ok(cindex_len) 691 Ok(rust_index_len)
675 } 692 }
676 693
677 /// This is scaffolding at this point, but it could also become 694 /// This is scaffolding at this point, but it could also become
678 /// a way to start a persistent nodemap or perform a 695 /// a way to start a persistent nodemap or perform a
679 /// vacuum / repack operation 696 /// vacuum / repack operation