<commit_before>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{AttributeValue, DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLineOffset,
            DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, DebugRngLists,
            EntriesTreeNode, Expression, Format, LittleEndian, LocationLists, Operation,
            RangeLists, Reader};
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;

pub fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);
    let unit = debug_info
        .units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
        test::black_box(
            unit.abbreviations(&debug_abbrev)
                .expect("Should parse abbreviations"),
        );
    });
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    let debug_info = read_section("debug_info");

    b.iter(|| {
        let debug_info = DebugInfo::new(&debug_info, LittleEndian);

        let mut iter = debug_info.units();
        while let Some(unit) = iter.next().expect("Should parse compilation unit") {
            let abbrevs = unit.abbreviations(&debug_abbrev)
                .expect("Should parse abbreviations");

            let mut cursor = unit.entries(&abbrevs);
            while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
                let mut attrs = entry.attrs();
                while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                    test::black_box(&attr);
                }
            }
        }
    });
}

#[bench]
fn bench_parsing_debug_info_tree(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);<commit_msg>Add a parse-self benchmark for `.debug_info` and `EndianRcSlice<commit_after>#![feature(test)]

extern crate gimli;
extern crate test;

use gimli::{AttributeValue, DebugAbbrev, DebugAranges, DebugInfo, DebugLine, DebugLineOffset,
            DebugLoc, DebugLocLists, DebugPubNames, DebugPubTypes, DebugRanges, DebugRngLists,
            EntriesTreeNode, Expression, Format, LittleEndian, LocationLists, Operation,
            RangeLists, Reader};
use std::env;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
use std::rc::Rc;

pub fn read_section(section: &str) -> Vec<u8> {
    let mut path = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".into()));
    path.push("./fixtures/self/");
    path.push(section);

    assert!(path.is_file());
    let mut file = File::open(path).unwrap();

    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();
    buf
}

#[bench]
fn bench_parsing_debug_abbrev(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);
    let unit = debug_info
        .units()
        .next()
        .expect("Should have at least one compilation unit")
        .expect("And it should parse OK");

    let debug_abbrev = read_section("debug_abbrev");

    b.iter(|| {
        let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
        test::black_box(
            unit.abbreviations(&debug_abbrev)
                .expect("Should parse abbreviations"),
        );
    });
}

#[inline]
fn impl_bench_parsing_debug_info<R: Reader>(debug_info: DebugInfo<R>, debug_abbrev: DebugAbbrev<R>) {
    let mut iter = debug_info.units();
    while let Some(unit) = iter.next().expect("Should parse compilation unit") {
        let abbrevs = unit.abbreviations(&debug_abbrev)
            .expect("Should parse abbreviations");

        let mut cursor = unit.entries(&abbrevs);
        while let Some((_, entry)) = cursor.next_dfs().expect("Should parse next dfs") {
            let mut attrs = entry.attrs();
            while let Some(attr) = attrs.next().expect("Should parse entry's attribute") {
                test::black_box(&attr);
            }
        }
    }
}

#[bench]
fn bench_parsing_debug_info(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = DebugInfo::new(&debug_info, LittleEndian);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);

    b.iter(|| impl_bench_parsing_debug_info(debug_info, debug_abbrev));
}

#[bench]
fn bench_parsing_debug_info_with_endian_rc_slice(b: &mut test::Bencher) {
    let debug_info = read_section("debug_info");
    let debug_info = Rc::from(&debug_info[..]);
    let debug_info = gimli::EndianRcSlice::new(debug_info, LittleEndian);
    let debug_info = DebugInfo::from(debug_info);

    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = Rc::from(&debug_abbrev[..]);
    let debug_abbrev = gimli::EndianRcSlice::new(debug_abbrev, LittleEndian);
    let debug_abbrev = DebugAbbrev::from(debug_abbrev);

    b.iter(|| impl_bench_parsing_debug_info(debug_info.clone(), debug_abbrev.clone()));
}

#[bench]
fn bench_parsing_debug_info_tree(b: &mut test::Bencher) {
    let debug_abbrev = read_section("debug_abbrev");
    let debug_abbrev = DebugAbbrev::new(&debug_abbrev, LittleEndian);
{'fraction_non_alphanumeric': 0.13795390482507047, 'fraction_numerical': 0.000331619963521804, 'mean_word_length': 3.594059405940594, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 10, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '458110', 'n_tokens_mistral': 2019, 'n_tokens_neox': 1929, 'n_words': 401}