Skip to content

Commit 8c63ab1

Browse files
Website: Implement a check for differing benchmark results and metadata (#144)
Co-authored-by: Siddharth Krishna <siddharth-krishna@users.noreply.github.com>
1 parent 908a114 commit 8c63ab1

File tree

7 files changed

+1157
-1920
lines changed

7 files changed

+1157
-1920
lines changed

results/benchmark_results.csv

Lines changed: 519 additions & 960 deletions
Large diffs are not rendered by default.

results/benchmark_results_mean_stddev.csv

Lines changed: 519 additions & 960 deletions
Large diffs are not rendered by default.

website-nextjs/eslint.config.mjs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ const compat = new FlatCompat({
1111

1212
const eslintConfig = [
1313
...compat.extends("next/core-web-vitals", "next/typescript"),
14+
{
15+
rules: {
16+
"react-hooks/exhaustive-deps": "off",
17+
},
18+
},
1419
];
1520

1621
export default eslintConfig;

website-nextjs/next.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import { validateData } from "@/scripts/validateData";
12
import type { NextConfig } from "next";
23

34
const nextConfig: NextConfig = {
45
reactStrictMode: true,
56
webpack(config) {
7+
// Validate the benchmark data before proceeding with the build.
8+
validateData();
9+
610
// Grab the existing rule that handles SVG imports
711
const fileLoaderRule = config.module.rules.find(
812
(rule: { test: { test: (arg0: string) => unknown } }) =>

website-nextjs/package-lock.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

website-nextjs/package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"compare-versions": "^6.1.1",
1717
"d3": "^7.9.0",
1818
"i": "^0.3.7",
19+
"js-yaml": "^4.1.0",
1920
"lodash": "^4.17.21",
2021
"lodash.camelcase": "^4.3.0",
2122
"next": "15.2.0",
@@ -34,6 +35,7 @@
3435
"devDependencies": {
3536
"@eslint/eslintrc": "^3",
3637
"@types/d3": "^7.4.3",
38+
"@types/js-yaml": "^4.0.9",
3739
"@types/lodash.camelcase": "^4.3.9",
3840
"@types/node": "^20",
3941
"@types/papaparse": "^5.3.15",
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import fs from "fs/promises";
3+
import path from "path";
4+
import Papa from "papaparse";
5+
import yaml from "js-yaml";
6+
7+
// Type definitions
8+
interface MetaData {
9+
[key: string]: any;
10+
}
11+
12+
interface BenchmarkResult {
13+
Benchmark: string;
14+
Size: string;
15+
benchmarkId: string;
16+
[key: string]: any;
17+
}
18+
19+
interface Size {
20+
size: string;
21+
[key: string]: any;
22+
}
23+
24+
// Path constants
25+
const RESULTS_DIR = path.resolve(process.cwd(), "../results");
26+
const METADATA_PATH = path.join(RESULTS_DIR, "metadata.yaml");
27+
const RESULTS_PATH = path.join(RESULTS_DIR, "benchmark_results.csv");
28+
29+
/**
30+
* Reads and parses the metadata YAML file
31+
* @returns The parsed metadata or null on error
32+
*/
33+
const getMetaData = async (): Promise<{ benchmarks: MetaData } | null> => {
34+
try {
35+
const yamlText = await fs.readFile(METADATA_PATH, "utf-8");
36+
const rawData = yaml.load(yamlText) as { benchmarks: MetaData };
37+
return rawData;
38+
} catch (error) {
39+
console.error("Error reading metadata:", error);
40+
return null;
41+
}
42+
};
43+
44+
/**
45+
* Reads and parses the benchmark results CSV file
46+
* @returns Array of benchmark results
47+
*/
48+
async function getBenchmarkResults(): Promise<BenchmarkResult[]> {
49+
try {
50+
const fileContent = await fs.readFile(RESULTS_PATH, "utf-8");
51+
const parsedResults = Papa.parse<BenchmarkResult>(fileContent, {
52+
header: true,
53+
skipEmptyLines: true,
54+
dynamicTyping: true,
55+
});
56+
return parsedResults.data;
57+
} catch (error) {
58+
console.error("Error reading benchmark results:", error);
59+
throw error;
60+
}
61+
}
62+
63+
/**
64+
* Validates that all benchmark results have corresponding metadata entries
65+
*/
66+
export async function validateData(): Promise<void> {
67+
try {
68+
const [results, metaData] = await Promise.all([
69+
getBenchmarkResults(),
70+
getMetaData(),
71+
]);
72+
73+
if (!metaData) {
74+
throw new Error("Failed to load metadata");
75+
}
76+
const invalidResults = results.filter((result) => {
77+
const benchmark = metaData.benchmarks[result.Benchmark];
78+
return (
79+
!benchmark ||
80+
!benchmark.Sizes?.some((s: Size) => s.Name === result.Size)
81+
);
82+
});
83+
84+
if (invalidResults.length > 0) {
85+
invalidResults.forEach((result) => {
86+
console.error(
87+
`Validation failed for benchmark: ${result.Benchmark} with size: ${result.Size}`,
88+
);
89+
});
90+
throw new Error(
91+
`${invalidResults.length} benchmark results failed validation`,
92+
);
93+
}
94+
} catch (error) {
95+
console.error("Error validating data:", error);
96+
throw error;
97+
}
98+
}

0 commit comments

Comments
 (0)