Box ShellError in Value::Error (#8375)

# Description

Our `ShellError` at the moment has a `std::mem::size_of<ShellError>` of
136 bytes (on AMD64). As a result `Value` directly storing the struct
also required 136 bytes (thanks to alignment requirements).

This change stores the `Value::Error` `ShellError` on the heap.

Pro:
- Value now needs just 80 bytes
- Should be 1 cacheline less (still at least 2 cachelines)

Con:
- More small heap allocations when dealing with `Value::Error`
  - More heap fragmentation
  - Potential for additional required memcopies

# Further code changes

Includes a small refactor of `try` due to a type mismatch in its large
match.

# User-Facing Changes

None for regular users.

Plugin authors may have to update their matches on `Value` if they use
`nu-protocol`

Needs benchmarking to see if there is a benefit in real world workloads.
**Update** small improvements in runtime for workloads with high volume
of values. Significant reduction in maximum resident set size, when many
values are held in memory.

# Tests + Formatting
This commit is contained in:
Stefan Holderbach
2023-03-12 09:57:27 +01:00
committed by GitHub
parent c26d91fb61
commit a52386e837
153 changed files with 648 additions and 520 deletions

View File

@ -134,7 +134,9 @@ fn operate(
Box::new(move |old| action(old, fgs_hex, fge_hex, bgs_hex, bge_hex, &head)),
);
if let Err(error) = r {
return Value::Error { error };
return Value::Error {
error: Box::new(error),
};
}
}
ret
@ -158,11 +160,11 @@ fn action(
(None, None, None, None) => {
// Error - no colors
Value::Error {
error: ShellError::MissingParameter {
error: Box::new(ShellError::MissingParameter {
param_name:
"please supply foreground and/or background color parameters".into(),
span: *command_span,
},
}),
}
}
(None, None, None, Some(bg_end)) => {
@ -286,10 +288,10 @@ fn action(
let got = format!("value is {}, not string", other.get_type());
Value::Error {
error: ShellError::TypeMismatch {
error: Box::new(ShellError::TypeMismatch {
err_message: got,
span: other.span().unwrap_or(*command_span),
},
}),
}
}
}

View File

@ -122,7 +122,9 @@ fn process_each_path(
Box::new(|v| process_value(v, text, command_span)),
);
if let Err(error) = ret {
return Value::Error { error };
return Value::Error {
error: Box::new(error),
};
}
}
value
@ -139,10 +141,10 @@ fn process_value(value: &Value, text: &Option<String>, command_span: &Span) -> V
let got = format!("value is {}, not string", other.get_type());
Value::Error {
error: ShellError::TypeMismatch {
error: Box::new(ShellError::TypeMismatch {
err_message: got,
span: other.span().unwrap_or(*command_span),
},
}),
}
}
}

View File

@ -58,10 +58,10 @@ fn action(input: &Value, _args: &CellPathOnlyArgs, command_span: Span) -> Value
let got = format!("value is {}, not string", other.get_type());
Value::Error {
error: ShellError::TypeMismatch {
error: Box::new(ShellError::TypeMismatch {
err_message: got,
span: other.span().unwrap_or(command_span),
},
}),
}
}
}