1import type { ChartData, Metric, Metrics } from "../types/data.js"; 2import type { Session } from "../wrappers/session.js"; 3 4/** 5 * Helps with transforming benchmark data into something that can be visualized easily. 6 */ 7export class Transforms { 8 private constructor() { 9 // static helpers. 10 } 11 12 static buildMetrics(session: Session, suppressed: Set<string>, suppressedMetrics: Set<string>): Metrics<number> { 13 const classGroups = Object.entries(session.classGroups); 14 const standard: Metric<number>[] = []; 15 const sampled: Metric<number[]>[] = []; 16 for (let i = 0; i < classGroups.length; i += 1) { 17 const [className, wrappers] = classGroups[i]; 18 for (let j = 0; j < wrappers.length; j += 1) { 19 const wrapper = wrappers[j]; 20 const datasetName = wrappers[j].value.datasetName(); 21 if (suppressed.has(datasetName)) { 22 continue; 23 } 24 const source = wrapper.source; 25 const testName = wrapper.value.testName(); 26 // standard 27 let labels = wrapper.value.metricLabels(); 28 for (let k = 0; k < labels.length; k += 1) { 29 const label = labels[k]; 30 if (suppressedMetrics.has(label)) { 31 continue; 32 } 33 const metric = wrapper.value.metric(label); 34 const charData: ChartData<number> = { 35 values: metric.runs 36 }; 37 Transforms.add<number>( 38 standard, 39 className, 40 testName, 41 label, 42 source, 43 charData 44 ); 45 } 46 // sampled 47 labels = wrapper.value.sampledLabels(); 48 for (let k = 0; k < labels.length; k += 1) { 49 const label = labels[k]; 50 if (suppressedMetrics.has(label)) { 51 continue; 52 } 53 const metric = wrapper.value.sampled(label); 54 const charData: ChartData<number[]> = { 55 values: metric.runs 56 }; 57 Transforms.add<number[]>( 58 sampled, 59 className, 60 testName, 61 label, 62 source, 63 charData 64 ); 65 } 66 } 67 } 68 const metrics: Metrics<number> = { 69 standard: standard, 70 sampled: sampled 71 }; 72 return metrics; 73 } 74 75 private static add<T>( 76 metrics: Metric<T>[], 77 className: string, 78 testName: string, 79 label: string, 80 source: string, 81 data: ChartData<T> 82 ) { 83 const metric = Transforms.getOrCreate<T>(metrics, className, testName, label); 84 metric.data[source] = data; 85 } 86 87 private static getOrCreate<T>( 88 metrics: Metric<T>[], 89 className: string, 90 testName: string, 91 label: string 92 ): Metric<T> { 93 let metric: Metric<T> | null = Transforms.find(metrics, className, testName, label); 94 if (metric == null) { 95 const data: Record<string, ChartData<T>> = {}; 96 metric = { 97 class: className, 98 benchmark: testName, 99 label: label, 100 data: data 101 } 102 metrics.push(metric); 103 } 104 return metric; 105 } 106 107 private static find<T>( 108 metrics: Metric<T>[], 109 className: string, 110 testName: string, 111 label: string 112 ): Metric<T> | null { 113 for (let i = 0; i < metrics.length; i += 1) { 114 const metric = metrics[i]; 115 if ( 116 metric.class === className && 117 metric.benchmark === testName && 118 metric.label === label 119 ) { 120 return metric; 121 } 122 } 123 return null; 124 } 125} 126