Shrink the size of Expr (#12610)

# Description
Continuing from #12568, this PR further reduces the size of `Expr` from
64 to 40 bytes. It also reduces `Expression` from 128 to 96 bytes and
`Type` from 32 to 24 bytes.

This was accomplished by:
- for `Expr` with multiple fields (e.g., `Expr::Thing(A, B, C)`),
merging the fields into new AST struct types and then boxing this struct
(e.g. `Expr::Thing(Box<ABC>)`).
- replacing `Vec<T>` with `Box<[T]>` in multiple places. `Expr`s and
`Expression`s should rarely be mutated, if at all, so this optimization
makes sense.

By reducing the size of these types, I didn't notice a large performance
improvement (at least compared to #12568). But this PR does reduce the
memory usage of nushell. My config is somewhat light so I only noticed a
difference of 1.4MiB (38.9MiB vs 37.5MiB).

---------

Co-authored-by: Stefan Holderbach <sholderbach@users.noreply.github.com>
This commit is contained in:
Ian Manske
2024-04-24 15:46:35 +00:00
committed by GitHub
parent c52884b3c8
commit 9996e4a1f8
195 changed files with 688 additions and 601 deletions

View File

@ -88,7 +88,7 @@ impl Expression {
pub fn as_keyword(&self) -> Option<&Expression> {
match &self.expr {
Expr::Keyword(_, _, expr) => Some(expr),
Expr::Keyword(kw) => Some(&kw.expr),
_ => None,
}
}
@ -189,7 +189,9 @@ impl Expression {
if head.has_in_variable(working_set) {
return true;
}
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in args {
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in
args.as_ref()
{
if expr.has_in_variable(working_set) {
return true;
}
@ -211,7 +213,7 @@ impl Expression {
Expr::Nothing => false,
Expr::GlobPattern(_, _) => false,
Expr::Int(_) => false,
Expr::Keyword(_, _, expr) => expr.has_in_variable(working_set),
Expr::Keyword(kw) => kw.expr.has_in_variable(working_set),
Expr::List(list) => {
for item in list {
if item.expr().has_in_variable(working_set) {
@ -230,18 +232,18 @@ impl Expression {
}
Expr::Operator(_) => false,
Expr::MatchBlock(_) => false,
Expr::Range(left, middle, right, ..) => {
if let Some(left) = &left {
Expr::Range(range) => {
if let Some(left) = &range.from {
if left.has_in_variable(working_set) {
return true;
}
}
if let Some(middle) = &middle {
if let Some(middle) = &range.next {
if middle.has_in_variable(working_set) {
return true;
}
}
if let Some(right) = &right {
if let Some(right) = &range.to {
if right.has_in_variable(working_set) {
return true;
}
@ -283,14 +285,14 @@ impl Expression {
false
}
}
Expr::Table(headers, cells) => {
for header in headers {
Expr::Table(table) => {
for header in table.columns.as_ref() {
if header.has_in_variable(working_set) {
return true;
}
}
for row in cells {
for row in table.rows.as_ref() {
for cell in row.iter() {
if cell.has_in_variable(working_set) {
return true;
@ -301,7 +303,7 @@ impl Expression {
false
}
Expr::ValueWithUnit(expr, _) => expr.has_in_variable(working_set),
Expr::ValueWithUnit(value) => value.expr.has_in_variable(working_set),
Expr::Var(var_id) => *var_id == IN_VARIABLE_ID,
Expr::VarDecl(_) => false,
}
@ -372,7 +374,9 @@ impl Expression {
Expr::DateTime(_) => {}
Expr::ExternalCall(head, args) => {
head.replace_span(working_set, replaced, new_span);
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in args {
for ExternalArgument::Regular(expr) | ExternalArgument::Spread(expr) in
args.as_mut()
{
expr.replace_span(working_set, replaced, new_span);
}
}
@ -391,7 +395,7 @@ impl Expression {
Expr::GlobPattern(_, _) => {}
Expr::MatchBlock(_) => {}
Expr::Int(_) => {}
Expr::Keyword(_, _, expr) => expr.replace_span(working_set, replaced, new_span),
Expr::Keyword(kw) => kw.expr.replace_span(working_set, replaced, new_span),
Expr::List(list) => {
for item in list {
item.expr_mut()
@ -399,14 +403,14 @@ impl Expression {
}
}
Expr::Operator(_) => {}
Expr::Range(left, middle, right, ..) => {
if let Some(left) = left {
Expr::Range(range) => {
if let Some(left) = &mut range.from {
left.replace_span(working_set, replaced, new_span)
}
if let Some(middle) = middle {
if let Some(middle) = &mut range.next {
middle.replace_span(working_set, replaced, new_span)
}
if let Some(right) = right {
if let Some(right) = &mut range.to {
right.replace_span(working_set, replaced, new_span)
}
}
@ -441,19 +445,19 @@ impl Expression {
*block_id = working_set.add_block(Arc::new(block));
}
Expr::Table(headers, cells) => {
for header in headers {
Expr::Table(table) => {
for header in table.columns.as_mut() {
header.replace_span(working_set, replaced, new_span)
}
for row in cells {
for row in table.rows.as_mut() {
for cell in row.iter_mut() {
cell.replace_span(working_set, replaced, new_span)
}
}
}
Expr::ValueWithUnit(expr, _) => expr.replace_span(working_set, replaced, new_span),
Expr::ValueWithUnit(value) => value.expr.replace_span(working_set, replaced, new_span),
Expr::Var(_) => {}
Expr::VarDecl(_) => {}
}