-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Java: add FT.INFO
#2405
Java: add FT.INFO
#2405
Conversation
9767901
to
27886e5
Compare
27886e5
to
a23acfa
Compare
for pair in map.iter_mut() { | ||
if pair.0 == Value::SimpleString("fields".into()) { | ||
let Value::Array(mut fields) = pair.1.clone() else { | ||
return Err(( | ||
ErrorKind::TypeError, | ||
"Response couldn't be converted for FT.INFO", | ||
format!("(`fields` was {:?})", get_value_type(&pair.1.clone())), | ||
) | ||
.into()); | ||
}; | ||
|
||
for field in fields.iter_mut() { | ||
let Value::Map(mut field_params) = convert_to_expected_type(field.clone(), Some(ExpectedReturnType::Map { | ||
key_type: &None, | ||
value_type: &None, | ||
})).unwrap() else { unreachable!() }; | ||
|
||
for pair in field_params.iter_mut() { | ||
if pair.0 == Value::SimpleString("vector_params".into()) { | ||
*pair = (pair.0.clone(), convert_to_expected_type(pair.1.clone(), Some(ExpectedReturnType::Map { | ||
key_type: &None, | ||
value_type: &None, | ||
}))?); | ||
break; | ||
} | ||
} | ||
|
||
*field = Value::Map(field_params); | ||
} | ||
|
||
*pair = (pair.0.clone(), Value::Array(fields)); | ||
break; | ||
} | ||
} | ||
Ok(Value::Map(map)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As requested, I dug into this a bit more to see if I could reduce the number of clones here. Here's what I've come up with:
for pair in map.iter_mut() { | |
if pair.0 == Value::SimpleString("fields".into()) { | |
let Value::Array(mut fields) = pair.1.clone() else { | |
return Err(( | |
ErrorKind::TypeError, | |
"Response couldn't be converted for FT.INFO", | |
format!("(`fields` was {:?})", get_value_type(&pair.1.clone())), | |
) | |
.into()); | |
}; | |
for field in fields.iter_mut() { | |
let Value::Map(mut field_params) = convert_to_expected_type(field.clone(), Some(ExpectedReturnType::Map { | |
key_type: &None, | |
value_type: &None, | |
})).unwrap() else { unreachable!() }; | |
for pair in field_params.iter_mut() { | |
if pair.0 == Value::SimpleString("vector_params".into()) { | |
*pair = (pair.0.clone(), convert_to_expected_type(pair.1.clone(), Some(ExpectedReturnType::Map { | |
key_type: &None, | |
value_type: &None, | |
}))?); | |
break; | |
} | |
} | |
*field = Value::Map(field_params); | |
} | |
*pair = (pair.0.clone(), Value::Array(fields)); | |
break; | |
} | |
} | |
Ok(Value::Map(map)) | |
let Some(fields_pair) = map.iter_mut().find(|(key, _)| { | |
*key == Value::SimpleString("fields".into()) | |
}) else { return Ok(Value::Map(map)) }; | |
let (fields_key, fields_value) = std::mem::replace(fields_pair, (Value::Nil, Value::Nil)); | |
let Value::Array(fields) = fields_value else { | |
return Err(( | |
ErrorKind::TypeError, | |
"Response couldn't be converted for FT.INFO", | |
format!("(`fields` was {:?})", get_value_type(&fields_value)), | |
).into()); | |
}; | |
let fields = fields.into_iter().map(|field| { | |
let Value::Map(mut field_params) = convert_to_expected_type(field, Some(ExpectedReturnType::Map { | |
key_type: &None, | |
value_type: &None, | |
}))? else { unreachable!() }; | |
let Some(vector_params_pair) = field_params.iter_mut().find(|(key, _)| { | |
*key == Value::SimpleString("vector_params".into()) | |
}) else { return Ok(Value::Map(field_params)) }; | |
let (vector_params_key, vector_params_value) = std::mem::replace(vector_params_pair, (Value::Nil, Value::Nil)); | |
let _ = std::mem::replace(vector_params_pair, (vector_params_key, convert_to_expected_type(vector_params_value, Some(ExpectedReturnType::Map { | |
key_type: &None, | |
value_type: &None, | |
}))?)); | |
Ok(Value::Map(field_params)) | |
}).collect::<RedisResult<Vec<Value>>>()?; | |
let _ = std::mem::replace(fields_pair, (fields_key, Value::Array(fields))); | |
Ok(Value::Map(map)) |
I gathered some stats to show that the number of allocations is reduced from 36 to 23. You might be wondering if that collect
call allocates memory. I checked, and it does not. The number of allocations is still 23, even if you use a mem replace instead.
Here's what heaptrack produces when I run this code in a small sample app:
Here is the sample app code (I expose glide_core client types and functions in public API just for testing purposes):
use redis::Value;
use glide_core::client::{ExpectedReturnType, convert_to_expected_type};
fn main() {
let value = Value::Array(vec![
Value::Array(vec![Value::SimpleString("fields".to_string()), Value::Array(vec![
Value::Array(vec![
Value::SimpleString("vector_params".to_string()),
Value::Array(vec![Value::SimpleString("hi".to_string()), Value::Int(42)])
])
])])
]);
convert_to_expected_type(value, Some(ExpectedReturnType::FTInfoReturnType)).unwrap();
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated, thank you for the review!
4274625
to
5a4cba3
Compare
Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
Signed-off-by: Yury-Fridlyand <yury.fridlyand@improving.com>
Issue link
#2428
Checklist
Before submitting the PR make sure the following are checked: