Mercurial > public > mercurial-scm > hg
view rust/hg-cpython/src/pybytes_deref.rs @ 51403:f8bf1a8e9181
phases: keep internal state as rev-num instead of node-id
Node-id are expensive to work with, dealing with revision is much simple and
faster.
The fact we still used node-id here shows how few effort have been put into
making the phase logic fast. We tend to no longer use node-id internally for
about ten years.
This has a large impact of repository with many draft roots. For example this
Mozilla-try copy have ? Million draft roots and `perf::unbundle` see a
significant improvement.
### data-env-vars.name = mozilla-try-2023-03-22-zstd-sparse-revlog
# benchmark.name = hg.perf.perf-unbundle
# bin-env-vars.hg.flavor = no-rust
# bin-env-vars.hg.py-re2-module = default
# benchmark.variants.issue6528 = disabled
# benchmark.variants.revs = last-1
before:: 1.746791 seconds
after:: 1.278379 seconds (-26.82%)
# benchmark.variants.revs = last-10
before:: 3.145774 seconds
after:: 2.103735 seconds (-33.13%)
# benchmark.variants.revs = last-100
before:: 3.487635 seconds
after:: 2.446749 seconds (-29.85%)
# benchmark.variants.revs = last-1000
before:: 5.007568 seconds
after:: 3.989923 seconds (-20.32%)
author | Pierre-Yves David <pierre-yves.david@octobus.net> |
---|---|
date | Tue, 20 Feb 2024 21:40:13 +0100 |
parents | be3b545c5cff |
children | 7346f93be7a4 |
line wrap: on
line source
use cpython::{PyBytes, Python}; use stable_deref_trait::StableDeref; /// Safe abstraction over a `PyBytes` together with the `&[u8]` slice /// that borrows it. Implements `Deref<Target = [u8]>`. /// /// Calling `PyBytes::data` requires a GIL marker but we want to access the /// data in a thread that (ideally) does not need to acquire the GIL. /// This type allows separating the call an the use. /// /// It also enables using a (wrapped) `PyBytes` in GIL-unaware generic code. pub struct PyBytesDeref { #[allow(unused)] keep_alive: PyBytes, /// Borrows the buffer inside `self.keep_alive`, /// but the borrow-checker cannot express self-referential structs. data: *const [u8], } impl PyBytesDeref { pub fn new(py: Python, bytes: PyBytes) -> Self { Self { data: bytes.data(py), keep_alive: bytes, } } pub fn unwrap(self) -> PyBytes { self.keep_alive } } impl std::ops::Deref for PyBytesDeref { type Target = [u8]; fn deref(&self) -> &[u8] { // Safety: the raw pointer is valid as long as the PyBytes is still // alive, and the returned slice borrows `self`. unsafe { &*self.data } } } unsafe impl StableDeref for PyBytesDeref {} fn require_send<T: Send>() {} #[allow(unused)] fn static_assert_pybytes_is_send() { #[allow(clippy::no_effect)] require_send::<PyBytes>; } // Safety: PyBytes is Send. Raw pointers are not by default, // but here sending one to another thread is fine since we ensure it stays // valid. unsafe impl Send for PyBytesDeref {}