]>
Commit | Line | Data |
---|---|---|
f9f354fc XL |
1 | #[macro_use] |
2 | extern crate criterion; | |
ea8adc8c XL |
3 | #[macro_use] |
4 | extern crate serde_derive; | |
8bb4bdeb | 5 | |
94222f64 XL |
6 | use criterion::Criterion; |
7 | use handlebars::{to_json, Context, Handlebars, Template}; | |
8 | use serde_json::value::Value as Json; | |
8bb4bdeb XL |
9 | use std::collections::BTreeMap; |
10 | ||
94222f64 | 11 | #[cfg(unix)] |
f9f354fc | 12 | use criterion::profiler::Profiler; |
94222f64 | 13 | #[cfg(unix)] |
3dfed10e | 14 | use pprof::protos::Message; |
94222f64 | 15 | #[cfg(unix)] |
3dfed10e | 16 | use pprof::ProfilerGuard; |
8bb4bdeb | 17 | |
94222f64 XL |
18 | #[cfg(unix)] |
19 | use std::fs::{create_dir_all, File}; | |
20 | #[cfg(unix)] | |
21 | use std::io::Write; | |
22 | #[cfg(unix)] | |
23 | use std::path::Path; | |
24 | ||
25 | #[cfg(unix)] | |
3dfed10e XL |
26 | #[derive(Default)] |
27 | struct CpuProfiler<'a> { | |
28 | guard: Option<ProfilerGuard<'a>>, | |
29 | } | |
f9f354fc | 30 | |
94222f64 | 31 | #[cfg(unix)] |
3dfed10e XL |
32 | impl<'a> Profiler for CpuProfiler<'a> { |
33 | fn start_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) { | |
f9f354fc | 34 | create_dir_all(&benchmark_dir).unwrap(); |
3dfed10e XL |
35 | |
36 | let guard = ProfilerGuard::new(100).unwrap(); | |
37 | self.guard = Some(guard); | |
f9f354fc XL |
38 | } |
39 | ||
3dfed10e XL |
40 | fn stop_profiling(&mut self, benchmark_id: &str, benchmark_dir: &Path) { |
41 | if let Ok(ref report) = self.guard.as_ref().unwrap().report().build() { | |
42 | let fg_file_name = benchmark_dir.join(format!("{}.svg", benchmark_id)); | |
43 | let fg_file = File::create(fg_file_name).unwrap(); | |
44 | report.flamegraph(fg_file).unwrap(); | |
45 | ||
46 | let pb_file_name = benchmark_dir.join(format!("{}.pb", benchmark_id)); | |
47 | let mut pb_file = File::create(pb_file_name).unwrap(); | |
48 | let profile = report.pprof().unwrap(); | |
49 | ||
50 | let mut content = Vec::new(); | |
51 | profile.encode(&mut content).unwrap(); | |
52 | pb_file.write_all(&content).unwrap(); | |
53 | }; | |
54 | ||
55 | self.guard = None; | |
f9f354fc XL |
56 | } |
57 | } | |
58 | ||
94222f64 | 59 | #[cfg(unix)] |
f9f354fc | 60 | fn profiled() -> Criterion { |
3dfed10e | 61 | Criterion::default().with_profiler(CpuProfiler::default()) |
f9f354fc XL |
62 | } |
63 | ||
64 | #[derive(Serialize)] | |
65 | struct DataWrapper { | |
66 | v: String, | |
67 | } | |
68 | ||
69 | #[derive(Serialize)] | |
70 | struct RowWrapper { | |
71 | real: Vec<DataWrapper>, | |
72 | dummy: Vec<DataWrapper>, | |
73 | } | |
74 | ||
75 | #[derive(Serialize)] | |
76 | struct NestedRowWrapper { | |
77 | parent: Vec<Vec<DataWrapper>>, | |
78 | } | |
79 | ||
8bb4bdeb XL |
80 | static SOURCE: &'static str = "<html> |
81 | <head> | |
82 | <title>{{year}}</title> | |
83 | </head> | |
84 | <body> | |
85 | <h1>CSL {{year}}</h1> | |
86 | <ul> | |
87 | {{#each teams}} | |
88 | <li class=\"{{#if @first}}champion{{/if}}\"> | |
89 | <b>{{name}}</b>: {{score}} | |
90 | </li> | |
91 | {{/each}} | |
92 | </ul> | |
93 | </body> | |
94 | </html>"; | |
95 | ||
96 | fn make_data() -> BTreeMap<String, Json> { | |
97 | let mut data = BTreeMap::new(); | |
98 | ||
9fa01778 | 99 | data.insert("year".to_string(), to_json("2015")); |
8bb4bdeb XL |
100 | |
101 | let mut teams = Vec::new(); | |
102 | ||
ea8adc8c XL |
103 | for v in vec![ |
104 | ("Jiangsu", 43u16), | |
105 | ("Beijing", 27u16), | |
106 | ("Guangzhou", 22u16), | |
107 | ("Shandong", 12u16), | |
416331ca XL |
108 | ] |
109 | .iter() | |
ea8adc8c | 110 | { |
8bb4bdeb XL |
111 | let (name, score) = *v; |
112 | let mut t = BTreeMap::new(); | |
9fa01778 XL |
113 | t.insert("name".to_string(), to_json(name)); |
114 | t.insert("score".to_string(), to_json(score)); | |
8bb4bdeb XL |
115 | teams.push(t) |
116 | } | |
117 | ||
041b39d2 | 118 | data.insert("teams".to_string(), to_json(&teams)); |
8bb4bdeb XL |
119 | data |
120 | } | |
121 | ||
f9f354fc XL |
122 | fn parse_template(c: &mut Criterion) { |
123 | c.bench_function("parse_template", move |b| { | |
124 | b.iter(|| Template::compile(SOURCE).ok().unwrap()) | |
125 | }); | |
8bb4bdeb XL |
126 | } |
127 | ||
f9f354fc | 128 | fn render_template(c: &mut Criterion) { |
8bb4bdeb | 129 | let mut handlebars = Handlebars::new(); |
ea8adc8c XL |
130 | handlebars |
131 | .register_template_string("table", SOURCE) | |
132 | .ok() | |
133 | .expect("Invalid template format"); | |
8bb4bdeb | 134 | |
3dfed10e | 135 | let ctx = Context::wraps(make_data()).unwrap(); |
f9f354fc | 136 | c.bench_function("render_template", move |b| { |
3dfed10e | 137 | b.iter(|| handlebars.render_with_context("table", &ctx).ok().unwrap()) |
f9f354fc | 138 | }); |
8bb4bdeb | 139 | } |
ea8adc8c | 140 | |
f9f354fc | 141 | fn large_loop_helper(c: &mut Criterion) { |
ea8adc8c XL |
142 | let mut handlebars = Handlebars::new(); |
143 | handlebars | |
144 | .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER") | |
145 | .ok() | |
146 | .expect("Invalid template format"); | |
147 | ||
148 | let real: Vec<DataWrapper> = (1..1000) | |
83c7162d XL |
149 | .map(|i| DataWrapper { |
150 | v: format!("n={}", i), | |
151 | }) | |
ea8adc8c XL |
152 | .collect(); |
153 | let dummy: Vec<DataWrapper> = (1..1000) | |
83c7162d XL |
154 | .map(|i| DataWrapper { |
155 | v: format!("n={}", i), | |
156 | }) | |
ea8adc8c XL |
157 | .collect(); |
158 | let rows = RowWrapper { real, dummy }; | |
f9f354fc | 159 | |
3dfed10e | 160 | let ctx = Context::wraps(&rows).unwrap(); |
f9f354fc | 161 | c.bench_function("large_loop_helper", move |b| { |
3dfed10e XL |
162 | b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap()) |
163 | }); | |
164 | } | |
165 | ||
166 | fn large_loop_helper_with_context_creation(c: &mut Criterion) { | |
167 | let mut handlebars = Handlebars::new(); | |
168 | handlebars | |
169 | .register_template_string("test", "BEFORE\n{{#each real}}{{this.v}}{{/each}}AFTER") | |
170 | .ok() | |
171 | .expect("Invalid template format"); | |
172 | ||
173 | let real: Vec<DataWrapper> = (1..1000) | |
174 | .map(|i| DataWrapper { | |
175 | v: format!("n={}", i), | |
176 | }) | |
177 | .collect(); | |
178 | let dummy: Vec<DataWrapper> = (1..1000) | |
179 | .map(|i| DataWrapper { | |
180 | v: format!("n={}", i), | |
181 | }) | |
182 | .collect(); | |
183 | let rows = RowWrapper { real, dummy }; | |
184 | ||
185 | c.bench_function("large_loop_helper_with_context_creation", move |b| { | |
f9f354fc XL |
186 | b.iter(|| handlebars.render("test", &rows).ok().unwrap()) |
187 | }); | |
ea8adc8c | 188 | } |
f9f354fc XL |
189 | |
190 | fn large_nested_loop(c: &mut Criterion) { | |
191 | let mut handlebars = Handlebars::new(); | |
192 | handlebars | |
193 | .register_template_string( | |
194 | "test", | |
195 | "BEFORE\n{{#each parent as |child|}}{{#each child}}{{this.v}}{{/each}}{{/each}}AFTER", | |
196 | ) | |
197 | .ok() | |
198 | .expect("Invalid template format"); | |
199 | ||
200 | let parent: Vec<Vec<DataWrapper>> = (1..100) | |
201 | .map(|_| { | |
202 | (1..10) | |
203 | .map(|v| DataWrapper { | |
204 | v: format!("v={}", v), | |
205 | }) | |
206 | .collect() | |
207 | }) | |
208 | .collect(); | |
209 | ||
210 | let rows = NestedRowWrapper { parent }; | |
211 | ||
3dfed10e | 212 | let ctx = Context::wraps(&rows).unwrap(); |
f9f354fc | 213 | c.bench_function("large_nested_loop", move |b| { |
3dfed10e | 214 | b.iter(|| handlebars.render_with_context("test", &ctx).ok().unwrap()) |
f9f354fc XL |
215 | }); |
216 | } | |
217 | ||
94222f64 | 218 | #[cfg(unix)] |
f9f354fc XL |
219 | criterion_group!( |
220 | name = benches; | |
221 | config = profiled(); | |
3dfed10e | 222 | targets = parse_template, render_template, large_loop_helper, large_loop_helper_with_context_creation, |
94222f64 | 223 | large_nested_loop |
f9f354fc | 224 | ); |
94222f64 XL |
225 | |
226 | #[cfg(not(unix))] | |
227 | criterion_group!( | |
228 | benches, | |
229 | parse_template, | |
230 | render_template, | |
231 | large_loop_helper, | |
232 | large_loop_helper_with_context_creation, | |
233 | large_nested_loop | |
234 | ); | |
235 | ||
f9f354fc | 236 | criterion_main!(benches); |