Remove benchmarks

Remove benchmark programs in favor of https://github.com/djc/template-benchmarks-rs

* Quite similar contents
* Some library has too heavy dependencies and frequently cause breaking
changes (which always results in tiny performance difference)
* Some benchmark implementation is out of date
* There is a persistent complaint that the benchmark is wrong (although
I'm not still convinced)

cc #28 #37
This commit is contained in:
Kogia-sima 2020-12-16 13:38:17 +09:00
parent 5961a7400b
commit 18ffe5b321
33 changed files with 2 additions and 3975 deletions

View File

@ -7,6 +7,5 @@ members = [
]
exclude = [
"sailfish-tests/fuzzing-tests",
"benches",
"examples"
]

View File

@ -17,7 +17,7 @@ Simple, small, and extremely fast template engine for Rust
- Simple and intuitive syntax inspired by [EJS](https://ejs.co/)
- Relatively small number of dependencies (<15 crates in total)
- Extremely fast (See [benchmarks](./benches/README.md))
- Extremely fast (See [benchmarks](https://github.com/djc/template-benchmarks-rs))
- Better error message
- Template rendering NEVER fails unless you explicitly return error.
- Syntax highlighting support ([vscode](./syntax/vscode), [vim](./syntax/vim))

2610
benches/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
[package]
name = "benches"
version = "0.2.3"
authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>", "Ryohei Machida <orcinus4627@gmail.com>"]
build = "src/build.rs"
edition = "2018"
publish = false
[dependencies]
askama = { git = "https://github.com/djc/askama" }
criterion = { version = "0.3", features = ["real_blackbox"] }
fomat-macros = { git = "https://github.com/krdln/fomat-macros" }
handlebars = { git = "https://github.com/sunng87/handlebars-rust" }
horrorshow = { git = "https://github.com/Stebalien/horrorshow-rs" }
liquid = "0.19.0"
markup = { git = "https://github.com/utkarshkukreti/markup.rs" }
maud = "0.21.0"
ramhorns = { git = "https://github.com/maciejhirsz/ramhorns" }
sailfish = { path = "../sailfish" }
sailfish-macros = { path = "../sailfish-macros" }
serde = "1"
serde_derive = "1"
serde_json = "1"
serde_yaml = "0.8"
tera = { git = "https://github.com/Keats/tera" }
v_htmlescape = "0.9.1"
yarte = { git = "https://github.com/botika/yarte", features = ["bytes-buf", "fixed"] }
bytes = "0.5.5"
[build-dependencies]
ructe = { git = "https://github.com/kaj/ructe" }
[[bench]]
name = "all"
harness = false

View File

@ -1,48 +1 @@
# Rust template engine benchmarks
Performance comparison of template engines for Rust based on [criterion](https://github.com/bheisler/criterion.rs) crate
## crates
- [askama](https://github.com/djc/askama): Type-safe, compiled Jinja-like templates for Rust
- [fomat](https://github.com/krdln/fomat-macros): Alternative syntax for printing macros in Rust
- [handlebars](https://github.com/sunng87/handlebars-rust): Handlebars templating language implemented in Rust and for Rust.
- [horrorshow](https://github.com/Stebalien/horrorshow-rs): A macro-based html builder for rust
- [liquid](https://github.com/cobalt-org/liquid-rust): the liquid templating language for Rust
- [markup](https://github.com/utkarshkukreti/markup.rs): A blazing fast, type-safe template engine for Rust.
- [maud](https://github.com/lambda-fairy/maud): Compile-time HTML templates for Rust
- [ramhorns](https://github.com/maciejhirsz/ramhorns): Fast Mustache template engine implementation in pure Rust
- [ructe](https://github.com/kaj/ructe): Rust Compiled Templates with static-file handling
- [std::write!](https://doc.rust-lang.org/std/macro.write.html): the std library `write!` macro
- [tera](https://github.com/Keats/tera): A template engine for Rust based on Jinja2/Django
- [yarte](https://github.com/botika/yarte): Yet Another Rust Template Engine, is the fastest template engine
- [sailfish](https://github.com/Kogia-sima/sailfish): Simple, small, and extremely fast template engine for Rust
## Running the benchmarks
```console
$ cargo bench
```
## Environment
- OS: Ubuntu 20.04 LTS
- CPU Model Name: Intel(R) Core(TM) i5-8265U CPU @ 1.60GHz
- BogoMIPS: 3600.00
## Results
- Big table
![Big table](./bigtable.png)
- Teams
![Teams](./teams.png)
## License
Copyright (c) 2020 Dirkjan Ochtman and Ryohei Machida
This benchmark code is distributed under the special permission granted by [Dirkjan Ochtman](https://github.com/djc) (See [this issue](https://github.com/djc/template-benchmarks-rs/issues/26)).
**You cannot modify or redistribute the source code without an explicit permission**.
benchmark programs were removed in favor of https://github.com/djc/template-benchmarks-rs

View File

@ -1,48 +0,0 @@
use benches::{
askama_bench, fomat, handlebars, horrorshow_bench, liquid, markup_bench, maud_bench,
ramhorns, ructe, sailfish, std_write, tera, yarte_bench, yarte_bytes, yarte_fixed,
};
use criterion::{criterion_group, criterion_main, Criterion};
fn big_table(c: &mut Criterion) {
let mut g = c.benchmark_group("Big table");
g.bench_function("Askama", |b| askama_bench::big_table(b, &100));
g.bench_function("fomat", |b| fomat::big_table(b, &100));
g.bench_function("Handlebars", |b| handlebars::big_table(b, &100));
g.bench_function("Horrorshow", |b| horrorshow_bench::big_table(b, &100));
g.bench_function("Liquid", |b| liquid::big_table(b, &100));
g.bench_function("Markup", |b| markup_bench::big_table(b, &100));
g.bench_function("Maud", |b| maud_bench::big_table(b, &100));
g.bench_function("Ramhorns", |b| ramhorns::big_table(b, &100));
g.bench_function("Ructe", |b| ructe::big_table(b, &100));
g.bench_function("Sailfish", |b| sailfish::big_table(b, &100));
g.bench_function("Tera", |b| tera::big_table(b, &100));
g.bench_function("Yarte", |b| yarte_bench::big_table(b, &100));
g.bench_function("Yarte Send", |b| yarte_bytes::big_table(b, &100));
g.bench_function("Yarte ?Send", |b| yarte_fixed::big_table(b, &100));
g.bench_function("write", |b| std_write::big_table(b, &100));
g.finish();
}
fn teams(c: &mut Criterion) {
let mut g = c.benchmark_group("Teams");
g.bench_function("Askama", |b| askama_bench::teams(b, &0));
g.bench_function("fomat", |b| fomat::teams(b, &0));
g.bench_function("Handlebars", |b| handlebars::teams(b, &0));
g.bench_function("Horrorshow", |b| horrorshow_bench::teams(b, &0));
g.bench_function("Liquid", |b| liquid::teams(b, &0));
g.bench_function("Markup", |b| markup_bench::teams(b, &0));
g.bench_function("Maud", |b| maud_bench::teams(b, &0));
g.bench_function("Ramhorns", |b| ramhorns::teams(b));
g.bench_function("Ructe", |b| ructe::teams(b, &0));
g.bench_function("Sailfish", |b| sailfish::teams(b));
g.bench_function("Tera", |b| tera::teams(b, &0));
g.bench_function("Yarte", |b| yarte_bench::teams(b));
g.bench_function("Yarte Send", |b| yarte_bytes::teams(b));
g.bench_function("Yarte ?Send", |b| yarte_fixed::teams(b));
g.bench_function("write", |b| std_write::teams(b, &0));
g.finish();
}
criterion_group!(benches, big_table, teams);
criterion_main!(benches);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

View File

@ -1,58 +0,0 @@
use askama::Template;
use criterion;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let ctx = BigTable { table };
b.iter(|| ctx.render().unwrap());
}
#[derive(Template)]
#[template(path = "big-table.html")]
struct BigTable {
table: Vec<Vec<usize>>,
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| teams.render().unwrap());
}
#[derive(Template)]
#[template(path = "teams.html")]
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,11 +0,0 @@
use ructe::Ructe;
use std::env;
use std::path::PathBuf;
fn main() {
let in_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap()).join("templates_ructe");
Ructe::from_env()
.unwrap()
.compile_templates(&in_dir)
.expect("compile templates");
}

View File

@ -1,76 +0,0 @@
use criterion;
use fomat_macros::fomat;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| {
fomat!(
"<table>\n"
for r1 in &table {
"<tr>\n"
for r2 in r1 { "<td>"(r2)"</td>" }
"\n</tr>\n"
}
"</table>"
)
});
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| {
fomat!(
"<html>
<head>
<title>"(teams.year)"</title>
</head>
<body>
<h1>CSL "(teams.year)"</h1>
<ul>"
for (i,team) in (&teams).teams.iter().enumerate() {
" <li class=\"" if i == 0 { "champion" } "\">\n"
" <b>"(team.name)"</b>: "(team.score)"\n"
" </li>\n"
}
"\n </ul>
</body>
</html>")
});
}
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,89 +0,0 @@
use std::collections::BTreeMap;
use ::handlebars::{to_json, Handlebars};
use criterion;
use serde::Serialize;
use serde_json;
use serde_json::value::Value as Json;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let ctx = BigTable { table };
let mut handlebars = Handlebars::new();
handlebars
.register_template_string("big-table.html", SOURCE)
.unwrap();
b.iter(|| handlebars.render("big-table.html", &ctx).ok().unwrap());
}
#[derive(Serialize)]
struct BigTable {
table: Vec<Vec<usize>>,
}
static SOURCE: &'static str = "<html>
{{#each table as |n|}}
<tr>{{#each n as |v|}}<td>{{v}}</td>{{/each}}</tr>
{{/each}}
</html>";
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let mut handlebars = Handlebars::new();
handlebars
.register_template_string("table", TEAMS_TEMPLATE)
.ok()
.expect("Invalid template format");
let data = teams_data();
b.iter(|| handlebars.render("table", &data).ok().unwrap())
}
fn teams_data() -> BTreeMap<String, Json> {
let mut data = BTreeMap::new();
data.insert("year".to_string(), to_json(&"2015".to_owned()));
let mut teams = Vec::new();
for v in vec![
("Jiangsu", 43u16),
("Beijing", 27u16),
("Guangzhou", 22u16),
("Shandong", 12u16),
]
.iter()
{
let (name, score) = *v;
let mut t = BTreeMap::new();
t.insert("name".to_string(), to_json(&name));
t.insert("score".to_string(), to_json(&score));
teams.push(t)
}
data.insert("teams".to_string(), to_json(&teams));
data
}
static TEAMS_TEMPLATE: &'static str = "<html>
<head>
<title>{{year}}</title>
</head>
<body>
<h1>CSL {{year}}</h1>
<ul>
{{#each teams}}
<li class=\"{{#if @first}}champion{{/if}}\">
<b>{{name}}</b>: {{score}}
</li>
{{/each}}
</ul>
</body>
</html>";

View File

@ -1,92 +0,0 @@
use criterion;
use horrorshow::html;
use horrorshow::prelude::*;
use horrorshow::Error;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| big_table_render(&table).unwrap());
}
fn big_table_render(table: &Vec<Vec<usize>>) -> Result<String, Error> {
let page = html! {
table {
@ for row in table {
tr {
@ for col in row {
td { : col }
}
}
}
}
};
page.into_string()
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| teams_render(&teams).unwrap());
}
fn teams_render(teams: &Teams) -> Result<String, Error> {
let page = html! {
html {
head {
title { : teams.year }
}
body {
h1 { : Raw("CSL ");
: teams.year
}
ul {
@ for (idx, team) in teams.teams.iter().enumerate() {
li(class? = if idx == 0 { Some(Raw("champion")) } else { None }) {
b { : &team.name }
: Raw(": ");
: team.score
}
}
}
}
}
};
page.into_string()
}
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,19 +0,0 @@
#![feature(proc_macro_hygiene)]
pub mod askama_bench;
pub mod fomat;
pub mod handlebars;
pub mod horrorshow_bench;
pub mod liquid;
pub mod markup_bench;
pub mod maud_bench;
pub mod ramhorns;
pub mod ructe;
pub mod sailfish;
pub mod std_write;
pub mod tera;
pub mod yarte_bench;
pub mod yarte_bytes;
pub mod yarte_fixed;
include!(concat!(env!("OUT_DIR"), "/templates.rs"));

View File

@ -1,75 +0,0 @@
use ::liquid::{
value::{Object, Value},
ParserBuilder,
};
use criterion;
use serde_yaml;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(Value::Scalar((i as i32).into()));
}
table.push(Value::Array(inner));
}
let template = ParserBuilder::with_liquid()
.build()
.unwrap()
.parse(
"<table>
{% for row in table %}
<tr>{% for col in row %}<td>{{ col|escape }}</td>{% endfor %}</tr>
{% endfor %}
</table>",
)
.unwrap();
let mut globals = Object::new();
globals.insert("table".into(), Value::Array(table));
b.iter(|| template.render(&globals));
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let parser = ParserBuilder::with_liquid()
.extra_filters()
.build()
.unwrap();
let template = parser.parse(TEAMS_TEMPLATE).unwrap();
let data: Object = self::serde_yaml::from_str(TEAMS_DATA).unwrap();
b.iter(|| template.render(&data));
}
static TEAMS_TEMPLATE: &'static str = "<html>
<head>
<title>{{year}}</title>
</head>
<body>
<h1>CSL {{year}}</h1>
<ul>
{% for team in teams %}
<li class=\"{% if forloop.first %}champion{% endif %}\">
<b>{{team.name}}</b>: {{team.score}}
</li>
{% endfor %}
</ul>
</body>
</html>";
static TEAMS_DATA: &'static str = "
year: 2015
teams:
- name: Jiangsu
score: 43
- name: Beijing
score: 27
- name: Guangzhou
score: 22
- name: Shandong
score: 12
";

View File

@ -1,83 +0,0 @@
use criterion;
use markup::define;
// TODO: Switch to `markup::define!` when upgrading to Rust 2018.
define! {
BigTable<'a>(table: &'a [Vec<usize>]) {
table {
@for r1 in table.iter() {
tr {
@for r2 in r1.iter() {
td { {*r2} }
}
}
}
}
}
}
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| BigTable { table: &table }.to_string());
}
pub struct Team {
name: String,
score: u8,
}
define! {
Teams<'a>(year: u32, teams: &'a [Team]) {
html {
head {
title { {year} }
}
body {
h1 { "CSL " {year} }
ul {
@for (index, team) in teams.iter().enumerate() {
li.{if index == 0 { Some("champion") } else { None }} {
b { {team.name} } ": " {team.score}
}
}
}
}
}
}
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let year = 2015;
let teams = vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
];
b.iter(|| {
Teams {
year,
teams: &teams,
}
.to_string()
});
}

View File

@ -1,92 +0,0 @@
use criterion;
use maud::html;
pub fn big_table(b: &mut criterion::Bencher, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| big_table_render(&table));
}
fn big_table_render(table: &Vec<Vec<usize>>) -> String {
let page = html! {
table {
@for row in table {
tr {
@for col in row {
td { (col) }
}
}
}
}
};
page.into_string()
}
pub fn teams(b: &mut criterion::Bencher, _: &usize) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| teams_render(&teams));
}
fn teams_render(teams: &Teams) -> String {
let page = html! {
html {
head {
title { (teams.year) }
}
body {
h1 {
"CSL "
(teams.year)
}
ul {
@for (idx, team) in teams.teams.iter().enumerate() {
li.champion[idx == 0] {
b { (&team.name) }
": "
(team.score)
}
}
}
}
}
};
page.into_string()
}
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,89 +0,0 @@
use ramhorns::{Template, Content};
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let tpl = Template::new(SOURCE).unwrap();
let ctx = BigTable { table };
b.iter(|| {
tpl.render(&ctx)
});
}
#[derive(Content)]
struct BigTable {
table: Vec<Vec<usize>>,
}
static SOURCE: &'static str = "<html>
{{#table}}
<tr>{{#.}}<td>{{.}}</td>{{/.}}</tr>
{{/table}}
</html>";
pub fn teams(b: &mut criterion::Bencher<'_>) {
let tpl = Template::new(TEAMS_TEMPLATE).unwrap();
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
class: "champion".into(),
score: 43,
},
Team {
name: "Beijing".into(),
class: String::new(),
score: 27,
},
Team {
name: "Guangzhou".into(),
class: String::new(),
score: 22,
},
Team {
name: "Shandong".into(),
class: String::new(),
score: 12,
},
],
};
b.iter(|| {
tpl.render(&teams)
});
}
#[derive(Content)]
struct Teams {
year: u16,
teams: Vec<Team>,
}
#[derive(Content)]
struct Team {
name: String,
class: String,
score: u8,
}
static TEAMS_TEMPLATE: &'static str = "<html>
<head>
<title>{{year}}</title>
</head>
<body>
<h1>CSL {{year}}</h1>
<ul>
{{#teams}}
<li class=\"{{class}}\">
<b>{{name}}</b>: {{score}}
</li>
{{/teams}}
</ul>
</body>
</html>";

View File

@ -1,48 +0,0 @@
use crate::templates;
use criterion;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| {
let mut buf = Vec::new();
templates::big_table(&mut buf, &table).unwrap();
});
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let year = 2015;
let teams = vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
];
b.iter(|| {
let mut buf = Vec::new();
templates::teams(&mut buf, year, &teams).unwrap();
});
}
pub struct Team {
pub name: String,
pub score: u8,
}

View File

@ -1,73 +0,0 @@
use sailfish::TemplateOnce;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| {
let ctx = BigTable { table: &table };
ctx.render_once().unwrap()
});
}
pub fn teams(b: &mut criterion::Bencher<'_>) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| {
let teams = TeamsTemplate {
year: teams.year,
teams: &teams.teams,
};
teams.render_once().unwrap()
});
}
#[derive(TemplateOnce)]
#[template(path = "big-table.stpl")]
#[template(rm_whitespace = true)]
struct BigTable<'a> {
table: &'a [Vec<usize>],
}
#[derive(TemplateOnce)]
#[template(path = "teams.stpl")]
#[template(rm_whitespace = true)]
struct TeamsTemplate<'a> {
year: u16,
teams: &'a [Team],
}
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,97 +0,0 @@
use std::io::Write;
use v_htmlescape::escape;
use criterion;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
b.iter(|| {
let mut output = Vec::new();
write!(&mut output, "<table>").unwrap();
for r1 in &table {
write!(&mut output, "<tr>\n").unwrap();
for r2 in r1 {
write!(&mut output, "<td>{col}</td>", col = r2).unwrap();
}
write!(&mut output, "</tr>\n").unwrap();
}
write!(&mut output, "</table>").unwrap();
output
});
}
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| {
let mut output = Vec::new();
write!(
&mut output,
"<html>
<head>
<title>{year}</title>
</head>
<body>
<h1>CSL {year}</h1>
<ul>",
year = teams.year
)
.unwrap();
for (i, team) in (&teams).teams.iter().enumerate() {
let champion = if i != 0 { "" } else { "champion" };
write!(
&mut output,
"<li class=\"{champion}\">
<b>{name}</b>: {score}",
champion = escape(champion),
name = escape(&team.name),
score = team.score
)
.unwrap();
}
write!(
&mut output,
" </ul>
</body>
</html>"
)
.unwrap();
output
});
}
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,84 +0,0 @@
use ::tera::{Context, Tera};
use criterion;
use serde::Serialize;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let mut tera = Tera::default();
tera.add_raw_templates(vec![("big-table.html", BIG_TABLE_TEMPLATE)])
.unwrap();
let mut ctx = Context::new();
ctx.insert("table", &table);
let _ = tera.render("big-table.html", &ctx).unwrap();
b.iter(|| tera.render("big-table.html", &ctx));
}
#[derive(Serialize)]
struct Team {
name: String,
score: u8,
}
// Tera doesn't allow `escape` on number values
static BIG_TABLE_TEMPLATE: &'static str = "<table>
{% for row in table %}
<tr>{% for col in row %}<td>{{ col }}</td>{% endfor %}</tr>
{% endfor %}
</table>";
pub fn teams(b: &mut criterion::Bencher<'_>, _: &usize) {
let mut tera = Tera::default();
tera.add_raw_templates(vec![("teams.html", TEAMS_TEMPLATE)])
.unwrap();
let mut ctx = Context::new();
ctx.insert("year", &2015);
ctx.insert(
"teams",
&vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
);
let _ = tera.render("teams.html", &ctx).unwrap();
b.iter(|| tera.render("teams.html", &ctx));
}
static TEAMS_TEMPLATE: &'static str = "<html>
<head>
<title>{{ year }}</title>
</head>
<body>
<h1>CSL {{ year }}</h1>
<ul>
{% for team in teams %}
<li class=\"{% if loop.first %}champion{% endif %}\">
<b>{{team.name}}</b>: {{team.score}}
</li>
{% endfor %}
</ul>
</body>
</html>";

View File

@ -1,58 +0,0 @@
use yarte::Template;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let ctx = BigTable { table };
b.iter(|| ctx.call().unwrap());
}
#[derive(Template)]
#[template(path = "big-table.hbs")]
struct BigTable {
table: Vec<Vec<usize>>,
}
pub fn teams(b: &mut criterion::Bencher<'_>) {
let teams = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| teams.call().unwrap());
}
#[derive(Template)]
#[template(path = "teams.hbs")]
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,59 +0,0 @@
use bytes::BytesMut;
use yarte::TemplateBytes;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let t = BigTable { table };
b.iter(|| t.call::<BytesMut>(109915));
}
#[derive(TemplateBytes)]
#[template(path = "big-table")]
struct BigTable {
table: Vec<Vec<usize>>,
}
pub fn teams(b: &mut criterion::Bencher<'_>) {
let t = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| t.call::<BytesMut>(239));
}
#[derive(TemplateBytes)]
#[template(path = "teams")]
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

View File

@ -1,64 +0,0 @@
use criterion::black_box;
use std::mem::MaybeUninit;
use yarte::TemplateFixed;
pub fn big_table(b: &mut criterion::Bencher<'_>, size: &usize) {
let mut table = Vec::with_capacity(*size);
for _ in 0..*size {
let mut inner = Vec::with_capacity(*size);
for i in 0..*size {
inner.push(i);
}
table.push(inner);
}
let t = BigTable { table };
b.iter(|| {
black_box(unsafe { t.call(&mut [MaybeUninit::uninit(); 109915]) }.unwrap());
});
}
#[derive(TemplateFixed)]
#[template(path = "big-table")]
struct BigTable {
table: Vec<Vec<usize>>,
}
pub fn teams(b: &mut criterion::Bencher<'_>) {
let t = Teams {
year: 2015,
teams: vec![
Team {
name: "Jiangsu".into(),
score: 43,
},
Team {
name: "Beijing".into(),
score: 27,
},
Team {
name: "Guangzhou".into(),
score: 22,
},
Team {
name: "Shandong".into(),
score: 12,
},
],
};
b.iter(|| {
black_box(unsafe { t.call(&mut [MaybeUninit::uninit(); 239]) }.unwrap());
});
}
#[derive(TemplateFixed)]
#[template(path = "teams")]
struct Teams {
year: u16,
teams: Vec<Team>,
}
struct Team {
name: String,
score: u8,
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

View File

@ -1 +0,0 @@
<table>{{#each table}}<tr>{{#each this}}<td>{{ this }}</td>{{/each }}</tr>{{/each }}</table>

View File

@ -1,5 +0,0 @@
<table>
{% for row in table %}
<tr>{% for col in row %}<td>{{ col|escape }}</td>{% endfor %}</tr>
{% endfor %}
</table>

View File

@ -1,3 +0,0 @@
<table>
<% for row in table { %><tr><% for col in row { %><td><%= *col %></td><% } %></tr><% } %>
</table>

View File

@ -1 +0,0 @@
<html><head><title>{{ year }}</title></head><body><h1>CSL {{ year }}</h1><ul>{{#each teams }}<li class="{{#if first }}champion{{/if }}"><b>{{ name }}</b>: {{ score }}</li>{{/each }}</ul></body></html>

View File

@ -1,15 +0,0 @@
<html>
<head>
<title>{{ year }}</title>
</head>
<body>
<h1>CSL {{ year }}</h1>
<ul>
{% for team in teams %}
<li class="{% if loop.index0 == 0 %}champion{% endif %}">
<b>{{ team.name }}</b>: {{ team.score }}
</li>
{% endfor %}
</ul>
</body>
</html>

View File

@ -1,11 +0,0 @@
<html>
<head>
<title><%= year %></title>
</head>
<body>
<h1>CSL <%= year %></h1>
<ul>
<% for (i, team) in teams.iter().enumerate() { %><li class="<% if i == 0 { %>champion<% } %>"><b><%= team.name %></b>: <%= team.score %></li><% } %>
</ul>
</body>
</html>

View File

@ -1,11 +0,0 @@
@(table: &Vec<Vec<usize>>)
<table>
@for row in table{
<tr>
@for col in row {
<td>@col</td>
}
</tr>
}
</table>

View File

@ -1,18 +0,0 @@
@use crate::ructe::Team;
@(year: u16, teams: &Vec<Team>)
<html>
<head>
<title>@year</title>
</head>
<body>
<h1>CSL @year</h1>
<ul>
@for (i, team) in teams.iter().enumerate(){
<li @if i==0 {class="champion"} else {}>
<b>@team.name</b>: @team.score
</li>
}
</ul>
</body>
</html>