Nothing fancy, like the others needs a bit more styling but should do for now.
ZEN3WUPDVQWI7LPTEG3WQA5QSEHU74CUXVFJJFIJNSIFC7N2CMEAC Style::Histogram => Bar::new()// TODO: charming does not support relative bar widths, but echarts does.// This is an exact value, NOT a percentage, and is wrong - each bar overlaps// itself. This is "fine" for a histogram, so leaving for now,// but should change eventually..bar_width(100).data(histogram::data(timings)).into(),
use crate::timings;use charming::{component::Axis, datatype::DataPoint, element::AxisType};const BUCKET_COUNT: usize = 10;fn find_min_max_duration(pkg_durations: &[f64]) -> (f64, f64) {assert!(!pkg_durations.is_empty());let mut min = f64::MAX;let mut max = f64::MIN;for duration in pkg_durations {min = duration.min(min);max = duration.max(max);}assert_ne!(min, f64::MAX);assert_ne!(max, f64::MIN);assert!(min.is_sign_positive());assert!(max.is_sign_positive());(min, max)}pub fn axes(timings: &timings::Output) -> (Axis, Axis) {let pkg_durations: Vec<f64> = timings.pkg_times().collect();let (min_duration, max_duration) = find_min_max_duration(&pkg_durations);let bucket_width = (max_duration - min_duration) / (BUCKET_COUNT as f64);let mut x_labels = Vec::with_capacity(BUCKET_COUNT);for bucket_index in 0..BUCKET_COUNT {// The start time is offset, first bucket starts at min_durationlet start_time = min_duration + (bucket_width * (bucket_index as f64));// The label is the start time rounded to 2 decimal placesx_labels.push(format!("{start_time:.2}"));}let x_axis = Axis::new().type_(AxisType::Category).data(x_labels);let y_axis = Axis::new().type_(AxisType::Value);(x_axis, y_axis)}pub fn data(timings: &timings::Output) -> Vec<DataPoint> {let pkg_durations: Vec<f64> = timings.pkg_times().collect();let (min_duration, max_duration) = find_min_max_duration(&pkg_durations);// Make sure to start the buckets at min, not 0let bucket_width = (max_duration - min_duration) / (BUCKET_COUNT as f64);let mut buckets = [0_u64; BUCKET_COUNT];for duration in pkg_durations {let relative_duration = duration - min_duration;let remainder = relative_duration % bucket_width;// Calculate the nearest multiple of bucket_sizelet next_multiple = (relative_duration - remainder) / bucket_width;// Make sure we have an integer before castingassert_eq!(next_multiple, next_multiple.floor());let bucket_index = next_multiple as usize;// Increment the frequency of the relevant bucketbuckets[bucket_index] += 1;}// Convert the buckets into `charming::datatype::DataPoint`sbuckets.into_iter().map(|bucket| (bucket as i64).into()).collect()}
}// TODO: this returns each total package time, but it would be interesting to filter by// crate type (lib, binary, proc_macro), target, build script runs etcpub fn pkg_times<'s>(&'s self) -> impl Iterator<Item = f64> + 's {self.repr.values().map(|messages| messages.iter().map(|msg| msg.duration).sum())