]> git.proxmox.com Git - rustc.git/blob - vendor/syn/benches/rust.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / vendor / syn / benches / rust.rs
1 // $ cargo bench --features full --bench rust
2 //
3 // Syn only, useful for profiling:
4 // $ RUSTFLAGS='--cfg syn_only' cargo build --release --features full --bench rust
5
6 #![cfg_attr(not(syn_only), feature(rustc_private))]
7 #![recursion_limit = "1024"]
8 #![allow(clippy::cast_lossless, clippy::unnecessary_wraps)]
9
10 #[macro_use]
11 #[path = "../tests/macros/mod.rs"]
12 mod macros;
13
14 #[path = "../tests/common/mod.rs"]
15 mod common;
16 #[path = "../tests/repo/mod.rs"]
17 mod repo;
18
19 use std::fs;
20 use std::time::{Duration, Instant};
21
22 #[cfg(not(syn_only))]
23 mod tokenstream_parse {
24 use proc_macro2::TokenStream;
25 use std::str::FromStr;
26
27 pub fn bench(content: &str) -> Result<(), ()> {
28 TokenStream::from_str(content).map(drop).map_err(drop)
29 }
30 }
31
32 mod syn_parse {
33 pub fn bench(content: &str) -> Result<(), ()> {
34 syn::parse_file(content).map(drop).map_err(drop)
35 }
36 }
37
38 #[cfg(not(syn_only))]
39 mod librustc_parse {
40 extern crate rustc_data_structures;
41 extern crate rustc_errors;
42 extern crate rustc_parse;
43 extern crate rustc_session;
44 extern crate rustc_span;
45
46 use rustc_data_structures::sync::Lrc;
47 use rustc_errors::{emitter::Emitter, Diagnostic, Handler};
48 use rustc_session::parse::ParseSess;
49 use rustc_span::source_map::{FilePathMapping, SourceMap};
50 use rustc_span::{edition::Edition, FileName};
51
52 pub fn bench(content: &str) -> Result<(), ()> {
53 struct SilentEmitter;
54
55 impl Emitter for SilentEmitter {
56 fn emit_diagnostic(&mut self, _diag: &Diagnostic) {}
57 fn source_map(&self) -> Option<&Lrc<SourceMap>> {
58 None
59 }
60 }
61
62 rustc_span::create_session_if_not_set_then(Edition::Edition2018, |_| {
63 let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
64 let emitter = Box::new(SilentEmitter);
65 let handler = Handler::with_emitter(false, None, emitter);
66 let sess = ParseSess::with_span_handler(handler, cm);
67 if let Err(diagnostic) = rustc_parse::parse_crate_from_source_str(
68 FileName::Custom("bench".to_owned()),
69 content.to_owned(),
70 &sess,
71 ) {
72 diagnostic.cancel();
73 return Err(());
74 };
75 Ok(())
76 })
77 }
78 }
79
80 #[cfg(not(syn_only))]
81 mod read_from_disk {
82 pub fn bench(content: &str) -> Result<(), ()> {
83 let _ = content;
84 Ok(())
85 }
86 }
87
88 fn exec(mut codepath: impl FnMut(&str) -> Result<(), ()>) -> Duration {
89 let begin = Instant::now();
90 let mut success = 0;
91 let mut total = 0;
92
93 walkdir::WalkDir::new("tests/rust/src")
94 .into_iter()
95 .filter_entry(repo::base_dir_filter)
96 .for_each(|entry| {
97 let entry = entry.unwrap();
98 let path = entry.path();
99 if path.is_dir() {
100 return;
101 }
102 let content = fs::read_to_string(path).unwrap();
103 let ok = codepath(&content).is_ok();
104 success += ok as usize;
105 total += 1;
106 if !ok {
107 eprintln!("FAIL {}", path.display());
108 }
109 });
110
111 assert_eq!(success, total);
112 begin.elapsed()
113 }
114
115 fn main() {
116 repo::clone_rust();
117
118 macro_rules! testcases {
119 ($($(#[$cfg:meta])* $name:ident,)*) => {
120 [
121 $(
122 $(#[$cfg])*
123 (stringify!($name), $name::bench as fn(&str) -> Result<(), ()>),
124 )*
125 ]
126 };
127 }
128
129 #[cfg(not(syn_only))]
130 {
131 let mut lines = 0;
132 let mut files = 0;
133 exec(|content| {
134 lines += content.lines().count();
135 files += 1;
136 Ok(())
137 });
138 eprintln!("\n{} lines in {} files", lines, files);
139 }
140
141 for (name, f) in testcases!(
142 #[cfg(not(syn_only))]
143 read_from_disk,
144 #[cfg(not(syn_only))]
145 tokenstream_parse,
146 syn_parse,
147 #[cfg(not(syn_only))]
148 librustc_parse,
149 ) {
150 eprint!("{:20}", format!("{}:", name));
151 let elapsed = exec(f);
152 eprintln!(
153 "elapsed={}.{:03}s",
154 elapsed.as_secs(),
155 elapsed.subsec_millis(),
156 );
157 }
158 eprintln!();
159 }