use criterion::{black_box, criterion_group, criterion_main, Criterion}; mod using_quote { use proc_macro2::TokenStream; use quote::quote; pub fn gen() -> TokenStream { let s = gen_struct(); let i = gen_impl(); quote!( #s #i ) } fn gen_struct() -> TokenStream { quote! { struct Foo { a: i64, b: i64, } } } fn gen_impl() -> TokenStream { quote! { impl Foo { fn bar(&self) { todo!() } } } } } // Faster than the "functional" quote approach, but ugly, and not as fast as `quote_into` mod quote_fragmented { use proc_macro2::TokenStream; use quote::quote; pub fn gen() -> TokenStream { let mut t = TokenStream::new(); gen_struct(&mut t); gen_impl(&mut t); t } fn gen_struct(t: &mut TokenStream) { t.extend(quote! { struct Foo { a: i64, b: i64, } }) } fn gen_impl(t: &mut TokenStream) { t.extend(quote! { impl Foo { fn bar(&self) { todo!() } } }); } } mod using_quote_into { use proc_macro2::TokenStream; use quote_into::quote_into; pub fn gen() -> TokenStream { let mut s = TokenStream::new(); gen_struct(&mut s); gen_impl(&mut s); s } fn gen_struct(s: &mut TokenStream) { quote_into! { s += struct Foo { a: i64, b: i64, } } } fn gen_impl(s: &mut TokenStream) { quote_into! { s += impl Foo { fn bar(&self) { todo!() } } } } } pub fn compare_simple(c: &mut Criterion) { { let a = using_quote::gen().to_string(); let b = quote_fragmented::gen().to_string(); let c = using_quote_into::gen().to_string(); assert_eq!(a, b); assert_eq!(b, c); } c.bench_function("quote", |b| b.iter(|| black_box(using_quote::gen()))); c.bench_function("quote_fragmented", |b| { b.iter(|| black_box(quote_fragmented::gen())) }); c.bench_function("quote_into", |b| { b.iter(|| black_box(using_quote_into::gen())) }); } criterion_group!(benches, compare_simple); criterion_main!(benches);