forked from extern/nushell
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:
@ -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(_) => {}
|
||||
}
|
||||
|
Reference in New Issue
Block a user