Rust 自作パーサーと正規表現のベンチマーク
テキスト中からURIを抜き出すためのライブラリを以前作ったんですが、これが正規表現と比べてどの程度速くなるのか確認しておきたいと思います。
まずベンチマークには ngihtly が必要なのでツールチェインをインストールしておきます。
rustup run nightly cargo run
次に適当なプロジェクトを作りますが、default は stable にしてあります。
cargo new bench_uri_extract
Cargo.tomlに必要なライブラリを追加。
[dependencies]
regex = "1"
parse-uri = {git = "https://github.com/iwot/parse-uri-rs.git", tag = "v0.1.7"}
main.rs に直接ベンチマークを記述。
#![feature(test)]
extern crate test;
// 省略
#[cfg(test)]
mod tests {
use super::*;
use test::Bencher;
#[bench]
fn bench_extract_uris(b: &mut Bencher) {
// 自作パーサーを使ってテキスト中のURIを抜き出す。
b.iter(|| {
let input = "あいうえお abc.ABC\r\nhttps://ccm.net/forum/affich-12027-finding-a-computer-name-using-ip\r\nかきくけこ https://github.com/iwot/parse-uri-rs
";
parser::extract_urls(&input)
});
}
#[bench]
fn bench_extract_uris_regex(b: &mut Bencher) {
// 正規表現を使ってテキスト中のURIを抜き出す。
let get_urls = move |text:&str, reg: Regex| -> Vec<String> {
let mut result = vec![];
for caps in reg.captures_iter(text) {
result.push(caps[0].to_string());
}
result
};
b.iter(|| {
let re_urls = Regex::new(r"(https?|ftp)(://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)").unwrap();
let input = "あいうえお abc.ABC\r\nhttps://ccm.net/forum/affich-12027-finding-a-computer-name-using-ip\r\nかきくけこ https://github.com/iwot/parse-uri-rs
";
get_urls(input, re_urls)
});
}
}
そして実際にベンチマークを取ります。
以下のようにすれば stable でも ngihtly のベンチマークが利用可能。
cargo +nightly bench
結果は以下のようになりました。
やっぱり正規表現は正規表現のビルドにコストがかかるみたいで、ぼちぼち差が出ました。
※ 24,095 ns/iter はイテレーション毎の平均が 24,095 ns ということだと思います。
test tests::bench_extract_uris ... bench: 24,095 ns/iter (+/- 941)
test tests::bench_extract_uris_regex ... bench: 127,427 ns/iter (+/- 7,646)
ちなみに次のように正規表現を使いまわしできる場合であれば、大量のデータを扱う場合でもちょっぱやにはなります。
※自作パーサーの10倍程度には速い。
#[bench]
fn bench_extract_uris_regex2(b: &mut Bencher) {
// 正規表現を使いまわして大量処理する場合はかなり速い。
let re_urls = Regex::new(r"(https?|ftp)(://[-_.!~*'()a-zA-Z0-9;/?:@&=+$,%#]+)").unwrap();
let get_urls = move |text:&str| -> Vec<String> {
let mut result = vec![];
for caps in re_urls.captures_iter(text) {
result.push(caps[0].to_string());
}
result
};
b.iter(|| {
let input = "あいうえお abc.ABC\r\nhttps://ccm.net/forum/affich-12027-finding-a-computer-name-using-ip\r\nかきくけこ https://github.com/iwot/parse-uri-rs
";
get_urls(input)
});
}
ベンチマーク結果。
test tests::bench_extract_uris ... bench: 24,075 ns/iter (+/- 974)
test tests::bench_extract_uris_regex ... bench: 123,875 ns/iter (+/- 14,675)
test tests::bench_extract_uris_regex2 ... bench: 2,783 ns/iter (+/- 255)
1プログラム中で何度もURIの抜き出しが必要な場合であれば正規表現を使いまわすほうが良い、と。
以上。