thag_rs 0.2.1

A versatile cross-platform playground and REPL for Rust snippets, expressions and programs. Accepts a script file or dynamic options.
Documentation
use rand::rngs::StdRng;
use rand::{Rng, SeedableRng};
use rayon::prelude::*;
use regex::Regex;
use serde_json::json;
use sha2::{Digest, Sha256};
use std::collections::HashMap;
use std::fs::File;
use std::io::{BufRead, BufReader, Write};
use std::time::Instant;

/// ChagtGPT-generated profiling synchronous time profiling benchmark: base code.
/// See `demo/benchmark*.rs` for `firestorm` and `thag_profiler` implementations.
///
//# Purpose: For checking and comparison of profiling tools
//# Categories: benchmark, profiling
const WORK_SIZE: usize = 500_000; // Increase this to scale up

fn generate_logs() -> Vec<String> {
    let mut rng = StdRng::seed_from_u64(42);
    let actions = ["login", "logout", "click", "scroll", "type"];
    (0..WORK_SIZE)
        .map(|_i| {
            let user = rng.random_range(1..100);
            let action = actions[rng.random_range(0..actions.len())];
            let time = rng.random_range(1..10_000);
            format!("INFO - user={user} action={action} time={time}")
        })
        .collect()
}

fn write_logs_to_file(filename: &str, logs: &[String]) {
    let mut file = File::create(filename).unwrap();
    for line in logs {
        writeln!(file, "{line}").unwrap();
    }
}

fn read_and_parse_logs(filename: &str) -> Vec<(u32, String, u64)> {
    let file = File::open(filename).unwrap();
    let reader = BufReader::new(file);
    let re = Regex::new(r"user=(\d+)\s+action=(\w+)\s+time=(\d+)").unwrap();

    reader
        .lines()
        .filter_map(|line| {
            let line = line.ok()?;
            let caps = re.captures(&line)?;
            Some((
                caps[1].parse().ok()?,
                caps[2].to_string(),
                caps[3].parse().ok()?,
            ))
        })
        .collect()
}

fn analyze(logs: &[(u32, String, u64)]) -> HashMap<String, u64> {
    let mut map = HashMap::new();
    for (_, action, time) in logs {
        *map.entry(action.clone()).or_insert(0) += time;
    }
    map
}

fn heavy_hashing_work(data: &[(u32, String, u64)]) -> Vec<String> {
    data.par_iter()
        .map(|(user, action, time)| {
            let mut hasher = Sha256::new();
            hasher.update(format!("{user}:{action}:{time}"));
            format!("{:x}", hasher.finalize())
        })
        .collect()
}

fn simulate_output(data: &HashMap<String, u64>, hashes: &[String]) {
    let summary = json!({
        "totals": data,
        "samples": &hashes[..std::cmp::min(10, hashes.len())],
    });
    println!("{summary}");
}

fn main() {
    let start = Instant::now();

    let logs = generate_logs();
    write_logs_to_file("benchmark.log", &logs);
    let parsed = read_and_parse_logs("benchmark.log");
    let summary = analyze(&parsed);
    let hashes = heavy_hashing_work(&parsed);
    simulate_output(&summary, &hashes);

    let elapsed = start.elapsed();
    eprintln!("Elapsed: {elapsed:.2?}");
}