##// END OF EJS Templates
sidedatacopies: fast path data fetching if revision has no sidedata...
sidedatacopies: fast path data fetching if revision has no sidedata When using the side data mode, we know their won't be any copy information sidedata. Skipping revision restoration give an important speed boost. In the future, there will be other user of sidedata, reducing the efficiency of this. We should consider adding a dedicated flag in revlog V2 to preserve this optimisation. The current situation is good enough for now. revision: large amount; added files: large amount; rename small amount; c3b14617fbd7 9ba6ab77fd29 before: ! wall 2.401569 comb 2.400000 user 2.390000 sys 0.010000 (median of 10) after: ! wall 1.429294 comb 1.430000 user 1.410000 sys 0.020000 (median of 10) revision: large amount; added files: small amount; rename small amount; c3b14617fbd7 f650a9b140d2 before: ! wall 3.519140 comb 3.520000 user 3.470000 sys 0.050000 (median of 10) after: ! wall 1.963332 comb 1.960000 user 1.960000 sys 0.000000 (median of 10) revision: large amount; added files: large amount; rename large amount; 08ea3258278e d9fa043f30c0 before: ! wall 0.593880 comb 0.600000 user 0.590000 sys 0.010000 (median of 15) after: ! wall 0.251679 comb 0.250000 user 0.250000 sys 0.000000 (median of 38) revision: small amount; added files: large amount; rename large amount; df6f7a526b60 a83dc6a2d56f before: ! wall 0.013414 comb 0.020000 user 0.020000 sys 0.000000 (median of 220) after: ! wall 0.013222 comb 0.020000 user 0.020000 sys 0.000000 (median of 223) revision: small amount; added files: large amount; rename small amount; 4aa4e1f8e19a 169138063d63 before: ! wall 0.002711 comb 0.000000 user 0.000000 sys 0.000000 (median of 1000) after: ! wall 0.001631 comb 0.000000 user 0.000000 sys 0.000000 (median of 1000) revision: small amount; added files: small amount; rename small amount; 4bc173b045a6 964879152e2e before: ! wall 0.000077 comb 0.000000 user 0.000000 sys 0.000000 (median of 12208) after: ! wall 0.000078 comb 0.000000 user 0.000000 sys 0.000000 (median of 12012) revision: medium amount; added files: large amount; rename medium amount; c95f1ced15f2 2c68e87c3efe before: ! wall 0.410067 comb 0.410000 user 0.410000 sys 0.000000 (median of 23) after: ! wall 0.207786 comb 0.200000 user 0.200000 sys 0.000000 (median of 46) revision: medium amount; added files: medium amount; rename small amount; d343da0c55a8 d7746d32bf9d before: ! wall 0.097004 comb 0.090000 user 0.090000 sys 0.000000 (median of 100) after: ! wall 0.038495 comb 0.030000 user 0.030000 sys 0.000000 (median of 100) Differential Revision: https://phab.mercurial-scm.org/D7074

File last commit:

r43479:1ca3823a default
r43591:8a292526 default
Show More
parsers.rs
176 lines | 5.2 KiB | application/rls-services+xml | RustLexer
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 // parsers.rs
//
// Copyright 2019 Raphaël Gomès <rgomes@octobus.net>
//
// This software may be used and distributed according to the terms of the
// GNU General Public License version 2 or any later version.
//! Bindings for the `hg::dirstate::parsers` module provided by the
//! `hg-core` package.
//!
//! From Python, this will be seen as `mercurial.rustext.parsers`
//!
use cpython::{
exc, PyBytes, PyDict, PyErr, PyInt, PyModule, PyResult, PyTuple, Python,
Yuya Nishihara
rust-parsers: fix unboxing of PyInt on Python 3...
r43061 PythonObject, ToPyObject,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 };
use hg::{
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 pack_dirstate, parse_dirstate, utils::hg_path::HgPathBuf,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 DirstatePackError, DirstateParents, DirstateParseError, PARENT_SIZE,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 };
use std::collections::HashMap;
Yuya Nishihara
rust: simply use TryInto to convert slice to array...
r43067 use std::convert::TryInto;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 use crate::dirstate::{extract_dirstate, make_dirstate_tuple};
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 use std::time::Duration;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
fn parse_dirstate_wrapper(
py: Python,
dmap: PyDict,
copymap: PyDict,
st: PyBytes,
) -> PyResult<PyTuple> {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let mut dirstate_map = HashMap::new();
let mut copies = HashMap::new();
match parse_dirstate(&mut dirstate_map, &mut copies, st.data(py)) {
Ok(parents) => {
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 for (filename, entry) in &dirstate_map {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 dmap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, filename.as_ref()),
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 make_dirstate_tuple(py, entry)?,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 for (path, copy_path) in copies {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 copymap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, path.as_ref()),
PyBytes::new(py, copy_path.as_ref()),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 Ok(
(PyBytes::new(py, &parents.p1), PyBytes::new(py, &parents.p2))
.to_py_object(py),
)
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 }
Err(e) => Err(PyErr::new::<exc::ValueError, _>(
py,
match e {
DirstateParseError::TooLittleData => {
"too little data for parents".to_string()
}
DirstateParseError::Overflow => {
"overflow in dirstate".to_string()
}
DirstateParseError::CorruptedEntry(e) => e,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 DirstateParseError::Damaged => {
"dirstate appears to be damaged".to_string()
}
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 },
)),
}
}
fn pack_dirstate_wrapper(
py: Python,
dmap: PyDict,
copymap: PyDict,
pl: PyTuple,
now: PyInt,
) -> PyResult<PyBytes> {
let p1 = pl.get_item(py, 0).extract::<PyBytes>(py)?;
let p1: &[u8] = p1.data(py);
let p2 = pl.get_item(py, 1).extract::<PyBytes>(py)?;
let p2: &[u8] = p2.data(py);
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 let mut dirstate_map = extract_dirstate(py, &dmap)?;
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 let copies: Result<HashMap<HgPathBuf, HgPathBuf>, PyErr> = copymap
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 .items(py)
.iter()
.map(|(key, value)| {
Ok((
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 HgPathBuf::from_bytes(key.extract::<PyBytes>(py)?.data(py)),
HgPathBuf::from_bytes(value.extract::<PyBytes>(py)?.data(py)),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 ))
})
.collect();
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 if p1.len() != PARENT_SIZE || p2.len() != PARENT_SIZE {
return Err(PyErr::new::<exc::ValueError, _>(
py,
"expected a 20-byte hash".to_string(),
));
}
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 match pack_dirstate(
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 &mut dirstate_map,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 &copies?,
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 DirstateParents {
Yuya Nishihara
rust: simply use TryInto to convert slice to array...
r43067 p1: p1.try_into().unwrap(),
p2: p2.try_into().unwrap(),
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 },
Yuya Nishihara
rust-parsers: fix unboxing of PyInt on Python 3...
r43061 Duration::from_secs(now.as_object().extract::<u64>(py)?),
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 ) {
Raphaël Gomès
rust-parsers: switch to parse/pack_dirstate to mutate-on-loop...
r42993 Ok(packed) => {
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 for (filename, entry) in &dirstate_map {
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 dmap.set_item(
py,
Raphaël Gomès
rust-hgpath: replace all paths and filenames with HgPath/HgPathBuf...
r43227 PyBytes::new(py, filename.as_ref()),
Yuya Nishihara
rust-cpython: add wrapper around decapsule_make_dirstate_tuple()...
r43479 make_dirstate_tuple(py, entry)?,
Raphaël Gomès
rust-parsers: move parser bindings to their own file and Python module...
r42992 )?;
}
Ok(PyBytes::new(py, &packed))
}
Err(error) => Err(PyErr::new::<exc::ValueError, _>(
py,
match error {
DirstatePackError::CorruptedParent => {
"expected a 20-byte hash".to_string()
}
DirstatePackError::CorruptedEntry(e) => e,
DirstatePackError::BadSize(expected, actual) => {
format!("bad dirstate size: {} != {}", actual, expected)
}
},
)),
}
}
/// Create the module, with `__package__` given from parent
pub fn init_parsers_module(py: Python, package: &str) -> PyResult<PyModule> {
let dotted_name = &format!("{}.parsers", package);
let m = PyModule::new(py, dotted_name)?;
m.add(py, "__package__", package)?;
m.add(py, "__doc__", "Parsers - Rust implementation")?;
m.add(
py,
"parse_dirstate",
py_fn!(
py,
parse_dirstate_wrapper(dmap: PyDict, copymap: PyDict, st: PyBytes)
),
)?;
m.add(
py,
"pack_dirstate",
py_fn!(
py,
pack_dirstate_wrapper(
dmap: PyDict,
copymap: PyDict,
pl: PyTuple,
now: PyInt
)
),
)?;
let sys = PyModule::import(py, "sys")?;
let sys_modules: PyDict = sys.get(py, "modules")?.extract(py)?;
sys_modules.set_item(py, dotted_name, &m)?;
Ok(m)
}