Skip to content

Commit

Permalink
derive: add benchmark
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Kijewski committed Jun 18, 2024
1 parent e2a2c23 commit 1719626
Show file tree
Hide file tree
Showing 14 changed files with 126 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
strategy:
matrix:
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,
]
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ members = [
"rinja_actix",
"rinja_axum",
"rinja_derive",
"rinja_derive_standalone",
"rinja_escape",
"rinja_parser",
"rinja_rocket",
Expand Down
4 changes: 2 additions & 2 deletions rinja_derive/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ use std::path::{Path, PathBuf};
use std::rc::Rc;
use std::{env, fs};

use parser::node::Whitespace;
use parser::Syntax;
#[cfg(feature = "serde")]
use serde::Deserialize;

use crate::{CompileError, FileInfo, CRATE};
use parser::node::Whitespace;
use parser::Syntax;

#[derive(Debug)]
pub(crate) struct Config<'a> {
Expand Down
5 changes: 3 additions & 2 deletions rinja_derive/src/heritage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ use std::collections::HashMap;
use std::path::Path;
use std::rc::Rc;

use crate::config::Config;
use crate::{CompileError, FileInfo};
use parser::node::{BlockDef, Macro};
use parser::{Node, Parsed, WithSpan};

use crate::config::Config;
use crate::{CompileError, FileInfo};

pub(crate) struct Heritage<'a> {
pub(crate) root: &'a Context<'a>,
pub(crate) blocks: BlockAncestry<'a>,
Expand Down
2 changes: 1 addition & 1 deletion rinja_derive/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ use std::rc::Rc;
use std::str::FromStr;

use mime::Mime;
use parser::{Node, Parsed, Syntax};
use quote::ToTokens;
use syn::punctuated::Punctuated;

use crate::config::{get_template_source, Config};
use crate::CompileError;
use parser::{Node, Parsed, Syntax};

pub(crate) struct TemplateInput<'a> {
pub(crate) ast: &'a syn::DeriveInput,
Expand Down
65 changes: 41 additions & 24 deletions rinja_derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,38 +1,57 @@
#![deny(elided_lifetimes_in_paths)]
#![deny(unreachable_pub)]

mod config;
mod generator;
mod heritage;
mod input;
#[cfg(test)]
mod tests;

use std::collections::HashMap;
use std::fmt;
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};
mod generator;
use generator::{Generator, MapChain};
mod heritage;
use heritage::{Context, Heritage};
mod input;
use input::{Print, TemplateArgs, TemplateInput};
#[cfg(test)]
mod tests;
use parser::{generate_error_info, strip_common, ErrorInfo, ParseError};
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))]
pub fn derive_template(input: TokenStream) -> TokenStream {
let ast = syn::parse::<syn::DeriveInput>(input).unwrap();
match build_template(&ast) {
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);
pub fn derive_template(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
derive_template2(input.into()).into()
}

pub_if_standalone! {
pub fn derive_template2(input: TokenStream) -> TokenStream {
let ast = syn::parse2(input).unwrap();
match build_template(&ast) {
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
}
}
}
Expand Down Expand Up @@ -138,9 +157,7 @@ impl CompileError {
}

fn into_compile_error(self) -> TokenStream {
syn::Error::new(self.span, self.msg)
.to_compile_error()
.into()
syn::Error::new(self.span, self.msg).to_compile_error()
}
}

Expand Down
5 changes: 3 additions & 2 deletions rinja_derive/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Files containing tests for generated code.
//! Files containing tests for generated code.

use crate::build_template;
use std::fmt::Write;

use crate::build_template;

#[test]
fn check_if_let() {
// This function makes it much easier to compare expected code by adding the wrapping around
Expand Down
43 changes: 43 additions & 0 deletions rinja_derive_standalone/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[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"
publish = false

[features]
default = ["__standalone"]
__standalone = []
config = ["serde", "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 change: 1 addition & 0 deletions rinja_derive_standalone/LICENSE-APACHE
1 change: 1 addition & 0 deletions rinja_derive_standalone/LICENSE-MIT
2 changes: 2 additions & 0 deletions rinja_derive_standalone/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
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.
25 changes: 25 additions & 0 deletions rinja_derive_standalone/benches/derive-template.rs
Original file line number Diff line number Diff line change
@@ -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 change: 1 addition & 0 deletions rinja_derive_standalone/src
1 change: 1 addition & 0 deletions rinja_derive_standalone/templates

0 comments on commit 1719626

Please sign in to comment.