Repository: TeXitoi/benchmarksgame-rs (language: rust)

Issue:
regex-dna with &[u8] matching
I have a [gist](https://gist.github.com/llogiq/67fa854d5d5f8afd7f079f2a441e7219) where I use `regex::bytes` instead of plain `regex`. I'd have thought that it should be faster (because we can get rid of the UTF-8 check), but in fact it is _slower_. @BurntSushi there's probably some reason for that, just a heads-up; if the bytes variant should get faster we can retry the measurements.

On my system:

| variant | wall | user | sys |
| --- | --- | --- | --- |
| UTF-8 | 1.52 | 3.94 | 0.33 |
| bytes | 2.23 | 4.50 | 0.35 |



Discussion / hints:
Yeah, I noticed this a few weeks ago and though it was curious. I actually can't think of any obvious reason why it's slower. My (more extensive) benchmark suite says `Regex::new` and `bytes::Regex::new` have comparable performance. I'll look into it.

Another thing you could try is `from_utf8_unchecked`.

Ahahahahaha. This is because `replace_all` in `Regex` uses `push_str`, which should be a `memcpy`. On the other hand, `bytes::Regex` uses `extend`, which seems to be slower, and therefore I'm guessing doesn't get optimized down to a `memcpy`. Nice.

OK, once I fixed that in `regex`, the best of 3 for `bytes::Regex` was `0.59s` and for `Regex` it was `0.61s`. I figured it would be that small. It's barely perceptible and probably in the noise because I not-so-infrequently see both of them get up to `0.7s`.

Ok then I'm going to wait for a new Regex release so I can submit it without complicating our makefile. Thanks @BurntSushi!


Fix patch:
diff --git a/Makefile b/Makefile
index 9b66237..ce70d5c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ SOURCES = $(wildcard src/*.rs)
 RUSTC ?= rustc
 RUSTC_FLAGS ?= -C opt-level=3 -C target-cpu=core2 -C lto
 RUSTC_FLAGS += -L ./lib
-REGEX ?= regex-0.1.66
+REGEX ?= regex-0.1.69
 ARENA ?= typed-arena-1.1.0
 NUM_CPU ?= num_cpus-0.2.11
 
diff --git a/src/regex_dna.rs b/src/regex_dna.rs
index 1442b19..0e6f4e0 100644
--- a/src/regex_dna.rs
+++ b/src/regex_dna.rs
@@ -7,31 +7,33 @@
 
 extern crate regex;
 
+use regex::bytes::Regex;
+
 use std::io::{self, Read};
 use std::sync::Arc;
 use std::thread;
 
-macro_rules! regex { ($re:expr) => { ::regex::Regex::new($re).unwrap() } }
+macro_rules! regex { ($re:expr) => { Regex::new($re).unwrap() } }
 
 fn main() {
-    let mut seq = String::with_capacity(50 * (1 << 20));
-    io::stdin().read_to_string(&mut seq).unwrap();
+    let mut seq = Vec::with_capacity(50 * (1 << 20));
+    io::stdin().read_to_end(&mut seq).unwrap();
     let ilen = seq.len();
 
-    seq = regex!(">[^\n]*\n|\n").replace_all(&seq, "");
+    seq = regex!(r">[^\n]*\n|\n").replace_all(&seq, &b""[..]);
     let clen = seq.len();
     let seq_arc = Arc::new(seq.clone());
 
     let variants = vec![
-        regex!("agggtaaa|tttaccct"),
-        regex!("[cgt]gggtaaa|tttaccc[acg]"),
-        regex!("a[act]ggtaaa|tttacc[agt]t"),
-        regex!("ag[act]gtaaa|tttac[agt]ct"),
-        regex!("agg[act]taaa|ttta[agt]cct"),
-        regex!("aggg[acg]aaa|ttt[cgt]ccct"),
-        regex!("agggt[cgt]aa|tt[acg]accct"),
-        regex!("agggta[cgt]a|t[acg]taccct"),
-        regex!("agggtaa[cgt]|[acg]ttaccct"),
+        regex!(r"agggtaaa|tttaccct"),
+        regex!(r"[cgt]gggtaaa|tttaccc[acg]"),
+        regex!(r"a[act]ggtaaa|tttacc[agt]t"),
+        regex!(r"ag[act]gtaaa|tttac[agt]ct"),
+        regex!(r"agg[act]taaa|ttta[agt]cct"),
+        regex!(r"aggg[acg]aaa|ttt[cgt]ccct"),
+        regex!(r"agggt[cgt]aa|tt[acg]accct"),
+        regex!(r"agggta[cgt]a|t[acg]taccct"),
+        regex!(r"agggtaa[cgt]|[acg]ttaccct"),
     ];
     let mut counts = vec![];
     for variant in variants {
@@ -42,17 +44,17 @@ fn main() {
     }
 
     let substs = vec![
-        (regex!("B"), "(c|g|t)"),
-        (regex!("D"), "(a|g|t)"),
-        (regex!("H"), "(a|c|t)"),
-        (regex!("K"), "(g|t)"),
-        (regex!("M"), "(a|c)"),
-        (regex!("N"), "(a|c|g|t)"),
-        (regex!("R"), "(a|g)"),
-        (regex!("S"), "(c|g)"),
-        (regex!("V"), "(a|c|g)"),
-        (regex!("W"), "(a|t)"),
-        (regex!("Y"), "(c|t)"),
+        (regex!(r"B"), &b"(c|g|t)"[..]),
+        (regex!(r"D"), &b"(a|g|t)"[..]),
+        (regex!(r"H"), &b"(a|c|t)"[..]),
+        (regex!(r"K"), &b"(g|t)"[..]),
+        (regex!(r"M"), &b"(a|c)"[..]),
+        (regex!(r"N"), &b"(a|c|g|t)"[..]),
+        (regex!(r"R"), &b"(a|g)"[..]),
+        (regex!(r"S"), &b"(c|g)"[..]),
+        (regex!(r"V"), &b"(a|c|g)"[..]),
+        (regex!(r"W"), &b"(a|t)"[..]),
+        (regex!(r"Y"), &b"(c|t)"[..]),
     ];
     let mut seq = seq;
     for (re, replacement) in substs.into_iter() {


Test patch: