mirror of
https://github.com/nushell/nushell.git
synced 2025-08-19 10:03:24 +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:
@@ -201,13 +201,13 @@ impl Value {
|
||||
// the `2`.
|
||||
|
||||
if let Value::Record { val, .. } = self {
|
||||
val.retain_mut(|key, value| {
|
||||
val.to_mut().retain_mut(|key, value| {
|
||||
let span = value.span();
|
||||
match key {
|
||||
// Grouped options
|
||||
"ls" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"use_ls_colors" => {
|
||||
@@ -236,7 +236,7 @@ impl Value {
|
||||
}
|
||||
"rm" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"always_trash" => {
|
||||
@@ -263,7 +263,7 @@ impl Value {
|
||||
"history" => {
|
||||
let history = &mut config.history;
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"isolation" => {
|
||||
@@ -305,7 +305,7 @@ impl Value {
|
||||
}
|
||||
"completions" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"quick" => {
|
||||
@@ -326,7 +326,7 @@ impl Value {
|
||||
}
|
||||
"external" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key3, value|
|
||||
val.to_mut().retain_mut(|key3, value|
|
||||
{
|
||||
let span = value.span();
|
||||
match key3 {
|
||||
@@ -393,7 +393,7 @@ impl Value {
|
||||
}
|
||||
"cursor_shape" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
let config_point = match key2 {
|
||||
"vi_insert" => &mut config.cursor_shape_vi_insert,
|
||||
@@ -426,7 +426,7 @@ impl Value {
|
||||
}
|
||||
"table" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"mode" => {
|
||||
@@ -451,7 +451,7 @@ impl Value {
|
||||
}
|
||||
Value::Record { val, .. } => {
|
||||
let mut invalid = false;
|
||||
val.retain(|key3, value| {
|
||||
val.to_mut().retain(|key3, value| {
|
||||
match key3 {
|
||||
"left" => {
|
||||
match value.as_int() {
|
||||
@@ -546,7 +546,7 @@ impl Value {
|
||||
}
|
||||
"filesize" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value| {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"metric" => {
|
||||
@@ -719,7 +719,7 @@ impl Value {
|
||||
},
|
||||
"datetime_format" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.retain_mut(|key2, value|
|
||||
val.to_mut().retain_mut(|key2, value|
|
||||
{
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
|
@@ -39,7 +39,7 @@ impl PluginGcConfigs {
|
||||
self.plugins = HashMap::new();
|
||||
}
|
||||
|
||||
val.retain_mut(|key, value| {
|
||||
val.to_mut().retain_mut(|key, value| {
|
||||
let span = value.span();
|
||||
match key {
|
||||
"default" => {
|
||||
@@ -88,7 +88,7 @@ fn process_plugins(
|
||||
// Remove any plugin configs that aren't in the value
|
||||
plugins.retain(|key, _| val.contains(key));
|
||||
|
||||
val.retain_mut(|key, value| {
|
||||
val.to_mut().retain_mut(|key, value| {
|
||||
if matches!(value, Value::Record { .. }) {
|
||||
plugins.entry(key.to_owned()).or_default().process(
|
||||
&join_path(path, &[key]),
|
||||
@@ -150,7 +150,7 @@ impl PluginGcConfig {
|
||||
self.stop_after = PluginGcConfig::default().stop_after;
|
||||
}
|
||||
|
||||
val.retain_mut(|key, value| {
|
||||
val.to_mut().retain_mut(|key, value| {
|
||||
let span = value.span();
|
||||
match key {
|
||||
"enabled" => process_bool_config(value, errors, &mut self.enabled),
|
||||
|
Reference in New Issue
Block a user