forked from extern/nushell
Copy-on-write for record values (#12305)
# Description This adds a `SharedCow` type as a transparent copy-on-write pointer that clones to unique on mutate. As an initial test, the `Record` within `Value::Record` is shared. There are some pretty big wins for performance. I'll post benchmark results in a comment. The biggest winner is nested access, as that would have cloned the records for each cell path follow before and it doesn't have to anymore. The reusability of the `SharedCow` type is nice and I think it could be used to clean up the previous work I did with `Arc` in `EngineState`. It's meant to be a mostly transparent clone-on-write that just clones on `.to_mut()` or `.into_owned()` if there are actually multiple references, but avoids cloning if the reference is unique. # User-Facing Changes - `Value::Record` field is a different type (plugin authors) # Tests + Formatting - 🟢 `toolkit fmt` - 🟢 `toolkit clippy` - 🟢 `toolkit test` - 🟢 `toolkit test stdlib` # After Submitting - [ ] use for `EngineState` - [ ] use for `Value::List`
This commit is contained in:
@ -267,7 +267,7 @@ fn compact_primitive_description(mut value: Value) -> Value {
|
||||
if val.len() != 1 {
|
||||
return value;
|
||||
}
|
||||
if let Some(type_name) = val.get_mut("type") {
|
||||
if let Some(type_name) = val.to_mut().get_mut("type") {
|
||||
return std::mem::take(type_name);
|
||||
}
|
||||
}
|
||||
@ -303,7 +303,8 @@ fn describe_value(
|
||||
),
|
||||
head,
|
||||
),
|
||||
Value::Record { mut val, .. } => {
|
||||
Value::Record { val, .. } => {
|
||||
let mut val = val.into_owned();
|
||||
for (_k, v) in val.iter_mut() {
|
||||
*v = compact_primitive_description(describe_value(
|
||||
std::mem::take(v),
|
||||
@ -317,7 +318,7 @@ fn describe_value(
|
||||
record!(
|
||||
"type" => Value::string("record", head),
|
||||
"lazy" => Value::bool(false, head),
|
||||
"columns" => Value::record(*val, head),
|
||||
"columns" => Value::record(val, head),
|
||||
),
|
||||
head,
|
||||
)
|
||||
@ -395,10 +396,11 @@ fn describe_value(
|
||||
|
||||
if options.collect_lazyrecords {
|
||||
let collected = val.collect()?;
|
||||
if let Value::Record { mut val, .. } =
|
||||
if let Value::Record { val, .. } =
|
||||
describe_value(collected, head, engine_state, options)?
|
||||
{
|
||||
record.push("length", Value::int(val.len() as i64, head));
|
||||
let mut val = Record::clone(&val);
|
||||
|
||||
for (_k, v) in val.iter_mut() {
|
||||
*v = compact_primitive_description(describe_value(
|
||||
std::mem::take(v),
|
||||
@ -408,7 +410,8 @@ fn describe_value(
|
||||
)?);
|
||||
}
|
||||
|
||||
record.push("columns", Value::record(*val, head));
|
||||
record.push("length", Value::int(val.len() as i64, head));
|
||||
record.push("columns", Value::record(val, head));
|
||||
} else {
|
||||
let cols = val.column_names();
|
||||
record.push("length", Value::int(cols.len() as i64, head));
|
||||
|
Reference in New Issue
Block a user