mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-24 13:33:50 +00:00
Reduce size of Expr
from 80 to 64 bytes (#9900)
## Summary This PR reduces the size of `Expr` from 80 to 64 bytes, by reducing the sizes of... - `ExprCall` from 72 to 56 bytes, by using boxed slices for `Arguments`. - `ExprCompare` from 64 to 48 bytes, by using boxed slices for its various vectors. In testing, the parser gets a bit faster, and the linter benchmarks improve quite a bit.
This commit is contained in:
parent
bd8123c0d8
commit
49fe1b85f2
78 changed files with 326 additions and 258 deletions
|
@ -81,16 +81,16 @@ type FunctionArgument = (
|
|||
pub(crate) fn parse_arguments(
|
||||
function_arguments: Vec<FunctionArgument>,
|
||||
) -> Result<ArgumentList, LexicalError> {
|
||||
let mut args = vec![];
|
||||
let mut keywords = vec![];
|
||||
|
||||
// First, run through the comments to determine the number of positional and keyword arguments.
|
||||
let mut keyword_names = FxHashSet::with_capacity_and_hasher(
|
||||
function_arguments.len(),
|
||||
BuildHasherDefault::default(),
|
||||
);
|
||||
let mut double_starred = false;
|
||||
for (name, value) in function_arguments {
|
||||
if let Some((start, end, name)) = name {
|
||||
let mut num_args = 0;
|
||||
let mut num_keywords = 0;
|
||||
for (name, value) in &function_arguments {
|
||||
if let Some((start, _end, name)) = name {
|
||||
// Check for duplicate keyword arguments in the call.
|
||||
if let Some(keyword_name) = &name {
|
||||
if !keyword_names.insert(keyword_name.to_string()) {
|
||||
|
@ -98,21 +98,17 @@ pub(crate) fn parse_arguments(
|
|||
LexicalErrorType::DuplicateKeywordArgumentError(
|
||||
keyword_name.to_string().into_boxed_str(),
|
||||
),
|
||||
start,
|
||||
*start,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
double_starred = true;
|
||||
}
|
||||
|
||||
keywords.push(ast::Keyword {
|
||||
arg: name,
|
||||
value,
|
||||
range: TextRange::new(start, end),
|
||||
});
|
||||
num_keywords += 1;
|
||||
} else {
|
||||
// Positional arguments mustn't follow keyword arguments.
|
||||
if !keywords.is_empty() && !is_starred(&value) {
|
||||
if num_keywords > 0 && !is_starred(value) {
|
||||
return Err(LexicalError::new(
|
||||
LexicalErrorType::PositionalArgumentError,
|
||||
value.start(),
|
||||
|
@ -126,9 +122,26 @@ pub(crate) fn parse_arguments(
|
|||
));
|
||||
}
|
||||
|
||||
num_args += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Second, push the arguments into vectors of exact capacity. This avoids a vector resize later
|
||||
// on when these vectors are boxed into slices.
|
||||
let mut args = Vec::with_capacity(num_args);
|
||||
let mut keywords = Vec::with_capacity(num_keywords);
|
||||
for (name, value) in function_arguments {
|
||||
if let Some((start, end, name)) = name {
|
||||
keywords.push(ast::Keyword {
|
||||
arg: name,
|
||||
value,
|
||||
range: TextRange::new(start, end),
|
||||
});
|
||||
} else {
|
||||
args.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(ArgumentList { args, keywords })
|
||||
}
|
||||
|
||||
|
|
|
@ -569,8 +569,7 @@ mod tests {
|
|||
#[cfg(target_pointer_width = "64")]
|
||||
#[test]
|
||||
fn size_assertions() {
|
||||
// 80 with Rustc >= 1.76, 88 with Rustc < 1.76
|
||||
assert!(matches!(std::mem::size_of::<ParenthesizedExpr>(), 80 | 88));
|
||||
assert_eq!(std::mem::size_of::<ParenthesizedExpr>(), 72);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1406,8 +1406,18 @@ NotTest<Goal>: crate::parser::ParenthesizedExpr = {
|
|||
|
||||
Comparison<Goal>: crate::parser::ParenthesizedExpr = {
|
||||
<location:@L> <left:Expression<"all">> <comparisons:(CompOp Expression<"all">)+> <end_location:@R> => {
|
||||
let (ops, comparators) = comparisons.into_iter().map(|(op, comparator)| (op, ast::Expr::from(comparator))).unzip();
|
||||
ast::ExprCompare { left: Box::new(left.into()), ops, comparators, range: (location..end_location).into() }.into()
|
||||
let mut ops = Vec::with_capacity(comparisons.len());
|
||||
let mut comparators = Vec::with_capacity(comparisons.len());
|
||||
for (op, comparator) in comparisons {
|
||||
ops.push(op);
|
||||
comparators.push(comparator.into());
|
||||
}
|
||||
ast::ExprCompare {
|
||||
left: Box::new(left.into()),
|
||||
ops: ops.into_boxed_slice(),
|
||||
comparators: comparators.into_boxed_slice(),
|
||||
range: (location..end_location).into(),
|
||||
}.into()
|
||||
},
|
||||
Expression<Goal>,
|
||||
};
|
||||
|
@ -1880,8 +1890,8 @@ Arguments: ast::Arguments = {
|
|||
<location:@L> "(" <e: Comma<FunctionArgument>> ")" <end_location:@R> =>? {
|
||||
let ArgumentList { args, keywords } = parse_arguments(e)?;
|
||||
Ok(ast::Arguments {
|
||||
args,
|
||||
keywords,
|
||||
args: args.into_boxed_slice(),
|
||||
keywords: keywords.into_boxed_slice(),
|
||||
range: (location..end_location).into()
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// auto-generated: "lalrpop 0.20.0"
|
||||
// sha3: fd05d84d3b654796ff740a7f905ec0ae8915f43f952428717735481947ab55e1
|
||||
// sha3: 02c60b5c591440061dda68775005d87a203b5448c205120bda1566a62fc2147c
|
||||
use ruff_text_size::{Ranged, TextLen, TextRange, TextSize};
|
||||
use ruff_python_ast::{self as ast, Int, IpyEscapeKind};
|
||||
use crate::{
|
||||
|
@ -36771,8 +36771,8 @@ fn __action241<
|
|||
{
|
||||
let ArgumentList { args, keywords } = parse_arguments(e)?;
|
||||
Ok(ast::Arguments {
|
||||
args,
|
||||
keywords,
|
||||
args: args.into_boxed_slice(),
|
||||
keywords: keywords.into_boxed_slice(),
|
||||
range: (location..end_location).into()
|
||||
})
|
||||
}
|
||||
|
@ -40651,8 +40651,18 @@ fn __action515<
|
|||
) -> crate::parser::ParenthesizedExpr
|
||||
{
|
||||
{
|
||||
let (ops, comparators) = comparisons.into_iter().map(|(op, comparator)| (op, ast::Expr::from(comparator))).unzip();
|
||||
ast::ExprCompare { left: Box::new(left.into()), ops, comparators, range: (location..end_location).into() }.into()
|
||||
let mut ops = Vec::with_capacity(comparisons.len());
|
||||
let mut comparators = Vec::with_capacity(comparisons.len());
|
||||
for (op, comparator) in comparisons {
|
||||
ops.push(op);
|
||||
comparators.push(comparator.into());
|
||||
}
|
||||
ast::ExprCompare {
|
||||
left: Box::new(left.into()),
|
||||
ops: ops.into_boxed_slice(),
|
||||
comparators: comparators.into_boxed_slice(),
|
||||
range: (location..end_location).into(),
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40816,8 +40826,18 @@ fn __action526<
|
|||
) -> crate::parser::ParenthesizedExpr
|
||||
{
|
||||
{
|
||||
let (ops, comparators) = comparisons.into_iter().map(|(op, comparator)| (op, ast::Expr::from(comparator))).unzip();
|
||||
ast::ExprCompare { left: Box::new(left.into()), ops, comparators, range: (location..end_location).into() }.into()
|
||||
let mut ops = Vec::with_capacity(comparisons.len());
|
||||
let mut comparators = Vec::with_capacity(comparisons.len());
|
||||
for (op, comparator) in comparisons {
|
||||
ops.push(op);
|
||||
comparators.push(comparator.into());
|
||||
}
|
||||
ast::ExprCompare {
|
||||
left: Box::new(left.into()),
|
||||
ops: ops.into_boxed_slice(),
|
||||
comparators: comparators.into_boxed_slice(),
|
||||
range: (location..end_location).into(),
|
||||
}.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue