aboutsummaryrefslogtreecommitdiff
path: root/syn/benches/rust.rs
diff options
context:
space:
mode:
Diffstat (limited to 'syn/benches/rust.rs')
-rw-r--r--syn/benches/rust.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/syn/benches/rust.rs b/syn/benches/rust.rs
new file mode 100644
index 0000000..941ecb9
--- /dev/null
+++ b/syn/benches/rust.rs
@@ -0,0 +1,158 @@
+// $ cargo bench --features full --bench rust
+//
+// Syn only, useful for profiling:
+// $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust
+
+#![cfg_attr(not(syn_only), feature(rustc_private))]
+#![recursion_limit = "1024"]
+
+#[macro_use]
+#[path = "../tests/macros/mod.rs"]
+mod macros;
+
+#[path = "../tests/common/mod.rs"]
+mod common;
+#[path = "../tests/repo/mod.rs"]
+mod repo;
+
+use std::fs;
+use std::time::{Duration, Instant};
+
+#[cfg(not(syn_only))]
+mod tokenstream_parse {
+ use proc_macro2::TokenStream;
+ use std::str::FromStr;
+
+ pub fn bench(content: &str) -> Result<(), ()> {
+ TokenStream::from_str(content).map(drop).map_err(drop)
+ }
+}
+
+mod syn_parse {
+ pub fn bench(content: &str) -> Result<(), ()> {
+ syn::parse_file(content).map(drop).map_err(drop)
+ }
+}
+
+#[cfg(not(syn_only))]
+mod libsyntax_parse {
+ extern crate rustc_data_structures;
+ extern crate rustc_parse;
+ extern crate rustc_span;
+ extern crate syntax;
+
+ use rustc_data_structures::sync::Lrc;
+ use rustc_span::FileName;
+ use syntax::edition::Edition;
+ use syntax::errors::{emitter::Emitter, Diagnostic, Handler};
+ use syntax::sess::ParseSess;
+ use syntax::source_map::{FilePathMapping, SourceMap};
+
+ pub fn bench(content: &str) -> Result<(), ()> {
+ struct SilentEmitter;
+
+ impl Emitter for SilentEmitter {
+ fn emit_diagnostic(&mut self, _diag: &Diagnostic) {}
+ fn source_map(&self) -> Option<&Lrc<SourceMap>> {
+ None
+ }
+ }
+
+ syntax::with_globals(Edition::Edition2018, || {
+ let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
+ let emitter = Box::new(SilentEmitter);
+ let handler = Handler::with_emitter(false, None, emitter);
+ let sess = ParseSess::with_span_handler(handler, cm);
+ if let Err(mut diagnostic) = rustc_parse::parse_crate_from_source_str(
+ FileName::Custom("bench".to_owned()),
+ content.to_owned(),
+ &sess,
+ ) {
+ diagnostic.cancel();
+ return Err(());
+ };
+ Ok(())
+ })
+ }
+}
+
+#[cfg(not(syn_only))]
+mod read_from_disk {
+ pub fn bench(content: &str) -> Result<(), ()> {
+ let _ = content;
+ Ok(())
+ }
+}
+
+fn exec(mut codepath: impl FnMut(&str) -> Result<(), ()>) -> Duration {
+ let begin = Instant::now();
+ let mut success = 0;
+ let mut total = 0;
+
+ walkdir::WalkDir::new("tests/rust/src")
+ .into_iter()
+ .filter_entry(repo::base_dir_filter)
+ .for_each(|entry| {
+ let entry = entry.unwrap();
+ let path = entry.path();
+ if path.is_dir() {
+ return;
+ }
+ let content = fs::read_to_string(path).unwrap();
+ let ok = codepath(&content).is_ok();
+ success += ok as usize;
+ total += 1;
+ if !ok {
+ eprintln!("FAIL {}", path.display());
+ }
+ });
+
+ assert_eq!(success, total);
+ begin.elapsed()
+}
+
+fn main() {
+ repo::clone_rust();
+
+ macro_rules! testcases {
+ ($($(#[$cfg:meta])* $name:path,)*) => {
+ vec![
+ $(
+ $(#[$cfg])*
+ (stringify!($name), $name as fn(&str) -> Result<(), ()>),
+ )*
+ ]
+ };
+ }
+
+ #[cfg(not(syn_only))]
+ {
+ let mut lines = 0;
+ let mut files = 0;
+ exec(|content| {
+ lines += content.lines().count();
+ files += 1;
+ Ok(())
+ });
+ eprintln!("\n{} lines in {} files", lines, files);
+ }
+
+ for (name, f) in testcases!(
+ #[cfg(not(syn_only))]
+ read_from_disk::bench,
+ #[cfg(not(syn_only))]
+ tokenstream_parse::bench,
+ syn_parse::bench,
+ #[cfg(not(syn_only))]
+ libsyntax_parse::bench,
+ ) {
+ eprint!("{:20}", format!("{}:", name));
+ let elapsed = exec(f);
+ eprintln!(
+ "elapsed={}.{:03}s",
+ elapsed.as_secs(),
+ elapsed.subsec_millis(),
+ );
+ }
+ eprintln!();
+}