mirror of
https://github.com/nushell/nushell.git
synced 2025-06-30 14:40:06 +02:00
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:
@ -4,6 +4,7 @@ use crate::{
|
||||
};
|
||||
use nu_color_config::StyleComputer;
|
||||
use nu_protocol::{Config, Record, TableMode, Value};
|
||||
use nu_utils::SharedCow;
|
||||
|
||||
pub struct CollapsedTable;
|
||||
|
||||
@ -48,8 +49,9 @@ fn colorize_value(value: &mut Value, config: &Config, style_computer: &StyleComp
|
||||
// Take ownership of the record and reassign to &mut
|
||||
// We do this to have owned keys through `.into_iter`
|
||||
let record = std::mem::take(val);
|
||||
*val = Box::new(
|
||||
*val = SharedCow::new(
|
||||
record
|
||||
.into_owned()
|
||||
.into_iter()
|
||||
.map(|(mut header, mut val)| {
|
||||
colorize_value(&mut val, config, style_computer);
|
||||
|
@ -89,7 +89,7 @@ fn build_table(
|
||||
|
||||
fn convert_nu_value_to_table_value(value: Value, config: &Config) -> TableValue {
|
||||
match value {
|
||||
Value::Record { val, .. } => build_vertical_map(*val, config),
|
||||
Value::Record { val, .. } => build_vertical_map(val.into_owned(), config),
|
||||
Value::List { vals, .. } => {
|
||||
let rebuild_array_as_map = is_valid_record(&vals) && count_columns_in_record(&vals) > 0;
|
||||
if rebuild_array_as_map {
|
||||
@ -195,7 +195,8 @@ fn build_map_from_record(vals: Vec<Value>, config: &Config) -> TableValue {
|
||||
for val in vals {
|
||||
match val {
|
||||
Value::Record { val, .. } => {
|
||||
for (i, (_key, val)) in val.into_iter().take(count_columns).enumerate() {
|
||||
for (i, (_key, val)) in val.into_owned().into_iter().take(count_columns).enumerate()
|
||||
{
|
||||
let cell = convert_nu_value_to_table_value(val, config);
|
||||
list[i].push(cell);
|
||||
}
|
||||
|
Reference in New Issue
Block a user