【发布时间】:2021-03-24 12:17:01
【问题描述】:
我正在开发一些性能至关重要的应用程序,我正在寻找改进它的机会。该应用广泛使用正则表达式(regex crate),例如:
use regex::Regex;
...
let Regex = Regex::new(r###"[a-z0-9%]{3,}"###).unwrap();
有没有机会将预编译的Regex 实例保存到缓冲区(想想Vec<u8>)并在以后加载预编译以避免多次编译(在docs 中看不到类似的东西)?
PS。我已经懒惰地这样做了:
lazy_static! {
static ref REGEX2: Regex = Regex::new(r###"[a-z0-9%]{3,}"###).unwrap();
}
如果有多次调用,尝试节省一些 CPU 周期(但这是另一回事)。
PS。出于好奇,我对代码进行了基准测试:
fn bench_regex_candidates(b: &mut Bencher) {
b.iter(|| {
Regex::new(r###"[a-z0-9%]{3,}"###).unwrap();
});
}
fn bench_regex_content(b: &mut Bencher) {
b.iter(|| {
Regex::new(r###"^([^*|@"!]*?)#([@?$])?#(.+)$"###).unwrap()
});
}
而且编译速度很快(相对来说,满足我的需要):
regex/candidates time: [22.021 us 22.684 us 23.689 us]
Found 11 outliers among 100 measurements (11.00%)
2 (2.00%) high mild
9 (9.00%) high severe
regex/content time: [36.542 us 36.687 us 36.845 us]
Found 8 outliers among 100 measurements (8.00%)
3 (3.00%) high mild
5 (5.00%) high severe
【问题讨论】:
-
这确实是一个有趣的问题。我认为没有一种好的方法可以做到这一点而不会招致一些不安全的编年史。让我们看看是否有人给我们惊喜!
-
您的构建时间是否受到正则表达式编译的负面影响?
-
@tadman 这与构建时间无关,而是与应用程序运行时间有关 - 正则表达式可以编译一次,然后重用,甚至预编译并捆绑到应用程序中。正则表达式也可以在运行时出现,因此我们可以分发预编译的正则表达式而不是文本表示
-
你有几个?除非它 > 10K,否则我几乎不怀疑您甚至可以测量实例化它们所需的时间。在探索这样的性能问题时,它可以帮助你故意让你的代码真正“愚蠢”,比如做比你需要的多 100 倍的工作,只是为了看看它是否真的减慢了任何速度。通常不会。
-
客观上我认为这里的解决方案是不使用正则表达式,而是将自己解析为代码。这总是更快,但要正确实施可能需要更多的麻烦。
标签: regex serialization rust deserialization