P.STR.04 在使用 Cow<'a, B>
时要注意选择合理场景以便最大化地优化性能
【描述】
Cow<'a, B>
可以减少不必要的内存拷贝。Cow 代表 Clone-On-Write,意味着,使用它可以只在必要的时候再进行拷贝。
但它并不是万能的,只有在需要大量读取数据但仅有少量情况需要修改时,Cow<'a, B>
才能真正起到优化性能的作用。
如果不在意依赖库过多,编译文件更大,也可以使用第三方库 regex
来处理大数据的搜索匹配和替换等需求,性能更佳。
【反例】
假设场景一:要处理的大文件中,至少一半数据包含转义符号
#![allow(unused)] fn main() { // 不符合:这种情况在输入不包含转义符号的数据时,也需要对所有字符进行匹配处理,性能较低 pub fn naive(input: &str) -> String { let mut output = String::new(); for c in input.chars() { match c { '<' => output.push_str("<"), '>' => output.push_str(">"), '&' => output.push_str("&"), _ => output.push(c) } } output } }
假设场景二:要处理的大文件中,几乎所有数据都包含转义符号。这种场景下,使用 Cow<'a, B>
对性能也无法起到太大的优化作用,此时宜尝试使用 regex
之类的高性能第三方库处理。
【正例】
假设场景一:要处理的大文件中,至少一半数据包含转义符号。
#![allow(unused)] fn main() { // 对输入的字符串进行转义 // 符合: 性能提升大概 1 倍 pub fn naive<'a, S: Into<Cow<'a, str>>>(input: S) -> Cow<'a, str> { let input = input.into(); fn is_trouble(c: char) -> bool { c == '<' || c == '>' || c == '&' } if input.contains(is_trouble) { let mut output = String::with_capacity(input.len()); for c in input.chars() { match c { '<' => output.push_str("<"), '>' => output.push_str(">"), '&' => output.push_str("&"), _ => output.push(c) } } // 只有在字符串修改的时候才使用 String Cow::Owned(output) } else { //其他情况使用 &str input } } }