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