mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
This PR builds on #3201 to further speed up the benchmarks and reduce CI time. * Build and run each benchmark as separate job (like before). * But now each bench is only built with the dependencies it needs. * For linter benchmarks, build benchmark in 1 job (like #3201 does). * Run each linter fixture in a separate job as they're slow. This reduces total time to complete benchmarks from between 6m-7m to ~4m40s. All the individual jobs complete in under 1m30s, except for building linter benchmark which takes 2m30s. So there won't be the problem of blocking the CI queue that there was before. NB: I did try this before, and didn't see a benefit. But I realized today what I was doing wrong - it only works once the caches are populated by a previous run on main branch. So the CI times in this PR won't look good, but once it's merged to main, it will take effect. Here it is running on main branch of my fork: https://github.com/overlookmotel/oxc/actions/runs/9030511348 I also added a step to delete the temp artefacts which aren't needed once the run has completed.
121 lines
3.7 KiB
Rust
121 lines
3.7 KiB
Rust
use std::{fmt, fs::read_to_string, str::FromStr};
|
|
|
|
use crate::project_root;
|
|
use crate::request::agent;
|
|
|
|
pub struct TestFiles {
|
|
files: Vec<TestFile>,
|
|
}
|
|
|
|
impl Default for TestFiles {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl TestFiles {
|
|
pub fn new() -> Self {
|
|
let files = Self::get_libs().into_iter().map(|file| TestFile::new(&file)).collect();
|
|
Self { files }
|
|
}
|
|
|
|
pub fn files(&self) -> &Vec<TestFile> {
|
|
&self.files
|
|
}
|
|
|
|
fn get_libs() -> Vec<String> {
|
|
let root = project_root();
|
|
read_to_string(root.join("./tasks/libs.txt"))
|
|
.unwrap()
|
|
.lines()
|
|
.map(ToString::to_string)
|
|
.collect::<Vec<_>>()
|
|
}
|
|
|
|
pub fn minimal() -> Self {
|
|
let files = Self::get_libs()
|
|
.into_iter()
|
|
.filter(|name| ["react", "antd", "typescript"].iter().any(|f| name.contains(f)))
|
|
.map(|file| TestFile::new(&file))
|
|
.collect();
|
|
Self { files }
|
|
}
|
|
|
|
pub fn complicated() -> Self {
|
|
let files = Self::complicated_urls().into_iter().map(TestFile::new).collect();
|
|
Self { files }
|
|
}
|
|
|
|
pub fn complicated_one(index: usize) -> Self {
|
|
let url = Self::complicated_urls()[index];
|
|
let file = TestFile::new(url);
|
|
Self { files: vec![file] }
|
|
}
|
|
|
|
fn complicated_urls() -> [&'static str; 5] {
|
|
[
|
|
// TypeScript syntax (2.81MB)
|
|
"https://raw.githubusercontent.com/microsoft/TypeScript/v5.3.3/src/compiler/checker.ts",
|
|
// Real world app tsx (1.0M)
|
|
"https://raw.githubusercontent.com/oxc-project/benchmark-files/main/cal.com.tsx",
|
|
// Real world content-heavy app jsx (3K)
|
|
"https://raw.githubusercontent.com/oxc-project/benchmark-files/main/RadixUIAdoptionSection.jsx",
|
|
// Heavy with classes (554K)
|
|
"https://cdn.jsdelivr.net/npm/pdfjs-dist@4.0.269/build/pdf.mjs",
|
|
// ES5 (3.9M)
|
|
"https://cdn.jsdelivr.net/npm/antd@5.12.5/dist/antd.js",
|
|
]
|
|
}
|
|
}
|
|
|
|
pub struct TestFile {
|
|
pub url: String,
|
|
pub file_name: String,
|
|
pub source_text: String,
|
|
}
|
|
|
|
impl TestFile {
|
|
/// # Errors
|
|
/// # Panics
|
|
pub fn new(url: &str) -> Self {
|
|
let (file_name, source_text) = Self::get_source_text(url).unwrap();
|
|
Self { url: url.to_string(), file_name, source_text }
|
|
}
|
|
|
|
/// # Errors
|
|
/// # Panics
|
|
pub fn get_source_text(lib: &str) -> Result<(String, String), String> {
|
|
let url = url::Url::from_str(lib).map_err(err_to_string)?;
|
|
|
|
let segments = url.path_segments().ok_or_else(|| "lib url has no segments".to_string())?;
|
|
|
|
let filename = segments.last().ok_or_else(|| "lib url has no segments".to_string())?;
|
|
|
|
let file = project_root().join("target").join(filename);
|
|
|
|
if let Ok(code) = std::fs::read_to_string(&file) {
|
|
println!("[{filename}] - using [{}]", file.display());
|
|
Ok((filename.to_string(), code))
|
|
} else {
|
|
println!("[{filename}] - Downloading [{lib}] to [{}]", file.display());
|
|
match agent().get(lib).call() {
|
|
Ok(response) => {
|
|
let mut reader = response.into_reader();
|
|
|
|
let _drop = std::fs::remove_file(&file);
|
|
let mut writer = std::fs::File::create(&file).map_err(err_to_string)?;
|
|
let _drop = std::io::copy(&mut reader, &mut writer);
|
|
|
|
std::fs::read_to_string(&file)
|
|
.map_err(err_to_string)
|
|
.map(|code| (filename.to_string(), code))
|
|
}
|
|
Err(e) => Err(format!("{e:?}")),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn err_to_string<E: fmt::Debug>(e: E) -> String {
|
|
format!("{e:?}")
|
|
}
|