mirror of
https://github.com/askama-rs/askama.git
synced 2025-10-02 15:25:19 +00:00
derive: add benchmark
This PR adds the crate "rinja_derive_standalone", which is just like "rinja_derive", though not a "proc_macro". This way we can easily expose it's internals for testing and benchmarking. Right now, the PR is more or less a prove of concept, and it probably needs a handful more useful benchmark use cases to be worth the hassle.
This commit is contained in:
parent
a6e98d5ef6
commit
1ce549d260
2
.github/workflows/rust.yml
vendored
2
.github/workflows/rust.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
package: [
|
package: [
|
||||||
rinja, rinja_actix, rinja_axum, rinja_derive, rinja_escape,
|
rinja, rinja_actix, rinja_axum, rinja_derive, rinja_derive_standalone, rinja_escape,
|
||||||
rinja_parser, rinja_rocket, rinja_warp, testing,
|
rinja_parser, rinja_rocket, rinja_warp, testing,
|
||||||
]
|
]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -4,6 +4,7 @@ members = [
|
|||||||
"rinja_actix",
|
"rinja_actix",
|
||||||
"rinja_axum",
|
"rinja_axum",
|
||||||
"rinja_derive",
|
"rinja_derive",
|
||||||
|
"rinja_derive_standalone",
|
||||||
"rinja_escape",
|
"rinja_escape",
|
||||||
"rinja_parser",
|
"rinja_parser",
|
||||||
"rinja_rocket",
|
"rinja_rocket",
|
||||||
|
@ -2,11 +2,12 @@ use std::collections::HashMap;
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::config::Config;
|
|
||||||
use crate::{CompileError, FileInfo};
|
|
||||||
use parser::node::{BlockDef, Macro};
|
use parser::node::{BlockDef, Macro};
|
||||||
use parser::{Node, Parsed, WithSpan};
|
use parser::{Node, Parsed, WithSpan};
|
||||||
|
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::{CompileError, FileInfo};
|
||||||
|
|
||||||
pub(crate) struct Heritage<'a> {
|
pub(crate) struct Heritage<'a> {
|
||||||
pub(crate) root: &'a Context<'a>,
|
pub(crate) root: &'a Context<'a>,
|
||||||
pub(crate) blocks: BlockAncestry<'a>,
|
pub(crate) blocks: BlockAncestry<'a>,
|
||||||
|
@ -4,12 +4,12 @@ use std::rc::Rc;
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
use parser::{Node, Parsed, Syntax};
|
||||||
use quote::ToTokens;
|
use quote::ToTokens;
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
|
|
||||||
use crate::config::{get_template_source, Config};
|
use crate::config::{get_template_source, Config};
|
||||||
use crate::CompileError;
|
use crate::CompileError;
|
||||||
use parser::{Node, Parsed, Syntax};
|
|
||||||
|
|
||||||
pub(crate) struct TemplateInput<'a> {
|
pub(crate) struct TemplateInput<'a> {
|
||||||
pub(crate) ast: &'a syn::DeriveInput,
|
pub(crate) ast: &'a syn::DeriveInput,
|
||||||
|
@ -1,38 +1,57 @@
|
|||||||
#![deny(elided_lifetimes_in_paths)]
|
#![deny(elided_lifetimes_in_paths)]
|
||||||
#![deny(unreachable_pub)]
|
#![deny(unreachable_pub)]
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
mod generator;
|
||||||
|
mod heritage;
|
||||||
|
mod input;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use proc_macro::TokenStream;
|
|
||||||
use proc_macro2::Span;
|
|
||||||
|
|
||||||
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError};
|
|
||||||
|
|
||||||
mod config;
|
|
||||||
use config::{read_config_file, Config};
|
use config::{read_config_file, Config};
|
||||||
mod generator;
|
|
||||||
use generator::{Generator, MapChain};
|
use generator::{Generator, MapChain};
|
||||||
mod heritage;
|
|
||||||
use heritage::{Context, Heritage};
|
use heritage::{Context, Heritage};
|
||||||
mod input;
|
|
||||||
use input::{Print, TemplateArgs, TemplateInput};
|
use input::{Print, TemplateArgs, TemplateInput};
|
||||||
#[cfg(test)]
|
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError};
|
||||||
mod tests;
|
use proc_macro2::{Span, TokenStream};
|
||||||
|
|
||||||
|
#[cfg(not(feature = "__standalone"))]
|
||||||
|
macro_rules! pub_if_standalone {
|
||||||
|
(pub $($tt:tt)*) => {
|
||||||
|
$($tt)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "__standalone")]
|
||||||
|
macro_rules! pub_if_standalone {
|
||||||
|
($($tt:tt)*) => {
|
||||||
|
$($tt)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(feature = "__standalone"))]
|
||||||
#[proc_macro_derive(Template, attributes(template))]
|
#[proc_macro_derive(Template, attributes(template))]
|
||||||
pub fn derive_template(input: TokenStream) -> TokenStream {
|
pub fn derive_template(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
|
derive_template2(input.into()).into()
|
||||||
match build_template(&ast) {
|
}
|
||||||
Ok(source) => source.parse().unwrap(),
|
|
||||||
Err(e) => {
|
pub_if_standalone! {
|
||||||
let mut e = e.into_compile_error();
|
pub fn derive_template2(input: TokenStream) -> TokenStream {
|
||||||
if let Ok(source) = build_skeleton(&ast) {
|
let ast = syn::parse2(input).unwrap();
|
||||||
let source: TokenStream = source.parse().unwrap();
|
match build_template(&ast) {
|
||||||
e.extend(source);
|
Ok(source) => source.parse().unwrap(),
|
||||||
|
Err(e) => {
|
||||||
|
let mut e = e.into_compile_error();
|
||||||
|
if let Ok(source) = build_skeleton(&ast) {
|
||||||
|
let source: TokenStream = source.parse().unwrap();
|
||||||
|
e.extend(source);
|
||||||
|
}
|
||||||
|
e
|
||||||
}
|
}
|
||||||
e
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -138,9 +157,7 @@ impl CompileError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn into_compile_error(self) -> TokenStream {
|
fn into_compile_error(self) -> TokenStream {
|
||||||
syn::Error::new(self.span, self.msg)
|
syn::Error::new(self.span, self.msg).to_compile_error()
|
||||||
.to_compile_error()
|
|
||||||
.into()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
// Files containing tests for generated code.
|
//! Files containing tests for generated code.
|
||||||
|
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
use crate::build_template;
|
use crate::build_template;
|
||||||
use std::fmt::Write;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_if_let() {
|
fn check_if_let() {
|
||||||
|
42
rinja_derive_standalone/Cargo.toml
Normal file
42
rinja_derive_standalone/Cargo.toml
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
[package]
|
||||||
|
name = "rinja_derive_standalone"
|
||||||
|
version = "0.13.0"
|
||||||
|
description = "Procedural macro package for Rinja"
|
||||||
|
homepage = "https://github.com/rinja-rs/rinja"
|
||||||
|
repository = "https://github.com/rinja-rs/rinja"
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
workspace = ".."
|
||||||
|
readme = "README.md"
|
||||||
|
edition = "2021"
|
||||||
|
rust-version = "1.65"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["__standalone"]
|
||||||
|
__standalone = []
|
||||||
|
config = ["dep:serde", "dep:basic-toml"]
|
||||||
|
humansize = []
|
||||||
|
urlencode = []
|
||||||
|
serde_json = []
|
||||||
|
num-traits = []
|
||||||
|
with-actix-web = []
|
||||||
|
with-axum = []
|
||||||
|
with-rocket = []
|
||||||
|
with-warp = []
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
parser = { package = "rinja_parser", version = "0.3", path = "../rinja_parser" }
|
||||||
|
mime = "0.3"
|
||||||
|
mime_guess = "2"
|
||||||
|
proc-macro2 = "1"
|
||||||
|
quote = "1"
|
||||||
|
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||||
|
syn = "2"
|
||||||
|
basic-toml = { version = "0.1.1", optional = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
criterion = "0.5"
|
||||||
|
|
||||||
|
[[bench]]
|
||||||
|
name = "derive-template"
|
||||||
|
harness = false
|
||||||
|
required-features = ["__standalone"]
|
1
rinja_derive_standalone/LICENSE-APACHE
Symbolic link
1
rinja_derive_standalone/LICENSE-APACHE
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../LICENSE-APACHE
|
1
rinja_derive_standalone/LICENSE-MIT
Symbolic link
1
rinja_derive_standalone/LICENSE-MIT
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../LICENSE-MIT
|
5
rinja_derive_standalone/README.md
Normal file
5
rinja_derive_standalone/README.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
This crate embeds the source of `rinja_derive`, but is not a `proc_macro`.
|
||||||
|
This way we can more easily access the internals of the crate.
|
||||||
|
|
||||||
|
To run the benchmark, execute `cargo bench` in this folder, or
|
||||||
|
`cargo bench -p rinja_derive_standalone` in the project root.
|
25
rinja_derive_standalone/benches/derive-template.rs
Normal file
25
rinja_derive_standalone/benches/derive-template.rs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
use criterion::{black_box, criterion_group, criterion_main, Criterion};
|
||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
criterion_main!(benches);
|
||||||
|
criterion_group!(benches, functions);
|
||||||
|
|
||||||
|
fn functions(c: &mut Criterion) {
|
||||||
|
c.bench_function("hello_world", hello_world);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn hello_world(b: &mut criterion::Bencher<'_>) {
|
||||||
|
let ts = quote! {
|
||||||
|
#[derive(Template)]
|
||||||
|
#[template(
|
||||||
|
source = "<html><body><h1>Hello, {{user}}!</h1></body></html>",
|
||||||
|
ext = "html"
|
||||||
|
)]
|
||||||
|
struct Hello<'a> {
|
||||||
|
user: &'a str,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
b.iter(|| {
|
||||||
|
rinja_derive_standalone::derive_template2(black_box(&ts).clone());
|
||||||
|
})
|
||||||
|
}
|
1
rinja_derive_standalone/src
Symbolic link
1
rinja_derive_standalone/src
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../rinja_derive/src/
|
1
rinja_derive_standalone/templates
Symbolic link
1
rinja_derive_standalone/templates
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../rinja_derive/templates/
|
Loading…
x
Reference in New Issue
Block a user