From a67dddb5f92c07c843a0d3d8c6036615c5221617 Mon Sep 17 00:00:00 2001
From: Ingvar Stepanyan <me@rreverser.com>
Date: Fri, 22 Jun 2018 14:40:24 +0100
Subject: [PATCH 1/2] Fix benchmark to reuse parsers

Initialisation of parser might be quite expensive, and, obviously, in real use-case it's meant to be reused, so this commit moves parser inits into lazy_static! block for more fair comparison.

Before:
```
running 3 tests
test bench_stabilizer ... bench:          30 ns/iter (+/- 10)
test smoke_uap        ... bench: 229,254,862 ns/iter (+/- 14,099,776)
test smoke_woothee    ... bench:       8,678 ns/iter (+/- 1,500)
```

After:
```
test bench_stabilizer ... bench:          24 ns/iter (+/- 2)
test smoke_uap        ... bench:     352,355 ns/iter (+/- 68,453)
test smoke_woothee    ... bench:       8,657 ns/iter (+/- 1,178)
```

Woothee is still much faster and hasn't changed numbers too much, but UAP numbers became ~650x better as they now measure just UA parsing and not loading the database.
---
 benches/benchmark.rs | 21 +++++++++++++--------
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/benches/benchmark.rs b/benches/benchmark.rs
index 697c833..d07810d 100644
--- a/benches/benchmark.rs
+++ b/benches/benchmark.rs
@@ -1,5 +1,7 @@
 #![feature(test)]
 
+#[macro_use]
+extern crate lazy_static;
 extern crate test;
 extern crate uap_rust;
 extern crate woothee;
@@ -8,18 +10,21 @@ use test::Bencher;
 use uap_rust::parser as uap;
 use woothee::parser as woo;
 
+lazy_static! {
+    static ref UAP_PARSER: uap::Parser = uap::Parser::new().unwrap();
+    static ref WOO_PARSER: woo::Parser = woo::Parser::new();
+}
+
 fn b_uap() {
-    let parser = uap::Parser::new().unwrap();
-    let _ = parser.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)".to_string());
-    let _ = parser.parse("Twitterbot/1.0".to_string());
-    let _ = parser.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)".to_string());
+    let _ = UAP_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)".to_string());
+    let _ = UAP_PARSER.parse("Twitterbot/1.0".to_string());
+    let _ = UAP_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)".to_string());
 }
 
 fn b_woothee() {
-    let parser = woo::Parser::new();
-    let _ = parser.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)");
-    let _ = parser.parse("Twitterbot/1.0");
-    let _ = parser.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)");
+    let _ = WOO_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)");
+    let _ = WOO_PARSER.parse("Twitterbot/1.0");
+    let _ = WOO_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)");
 }
 
 #[bench]

From 5df9c4ae2cc01c4a8d6afb07fb7e36c821cc18e4 Mon Sep 17 00:00:00 2001
From: Ingvar Stepanyan <me@rreverser.com>
Date: Fri, 22 Jun 2018 14:41:43 +0100
Subject: [PATCH 2/2] Use black_box in benchmarks

Make sure that result values are not optimised away.
---
 benches/benchmark.rs | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/benches/benchmark.rs b/benches/benchmark.rs
index d07810d..4db4e06 100644
--- a/benches/benchmark.rs
+++ b/benches/benchmark.rs
@@ -6,7 +6,7 @@ extern crate test;
 extern crate uap_rust;
 extern crate woothee;
 
-use test::Bencher;
+use test::{Bencher, black_box};
 use uap_rust::parser as uap;
 use woothee::parser as woo;
 
@@ -16,15 +16,15 @@ lazy_static! {
 }
 
 fn b_uap() {
-    let _ = UAP_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)".to_string());
-    let _ = UAP_PARSER.parse("Twitterbot/1.0".to_string());
-    let _ = UAP_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)".to_string());
+    black_box(UAP_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)".to_string()));
+    black_box(UAP_PARSER.parse("Twitterbot/1.0".to_string()));
+    black_box(UAP_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)".to_string()));
 }
 
 fn b_woothee() {
-    let _ = WOO_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)");
-    let _ = WOO_PARSER.parse("Twitterbot/1.0");
-    let _ = WOO_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)");
+    black_box(WOO_PARSER.parse("Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)"));
+    black_box(WOO_PARSER.parse("Twitterbot/1.0"));
+    black_box(WOO_PARSER.parse("Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; Xbox)"));
 }
 
 #[bench]