Skip to content

Commit

Permalink
Benchmarks: Install node_modules and reuse test directories (#284)
Browse files Browse the repository at this point in the history
This:

* Runs `npm install` in test directories to provide turbopack with modules necessary to bundle them.
* Reuses test directories for iterations across the given benchmark. This prevents unnecessary file writing and `npm install` for each iteration, improving the times to run benchmarks.

Currently cherry-picks #278 as it's necessary along with #277.

Test Plan: Connected to the running devserver mid-test and confirmed no errors are thrown and the triangle is rendered correctly.
  • Loading branch information
wbinnssmith committed Aug 29, 2022
1 parent 409c8fb commit d3c8138
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 21 deletions.
56 changes: 36 additions & 20 deletions crates/next-dev/benches/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{
fs::remove_dir_all,
future::Future,
io::{BufRead, BufReader},
io::{self, BufRead, BufReader, Write},
path::PathBuf,
process::{Child, ChildStdout, Command, Stdio},
time::Duration,
Expand Down Expand Up @@ -34,51 +34,43 @@ fn bench_startup(c: &mut Criterion) {

for size in [100, 1_000] {
g.bench_with_input(BenchmarkId::new("modules", size), &size, |b, &s| {
let test_dir = build_test(s);
b.to_async(&runtime).iter_batched_async(
|| PreparedApp::new(s),
|mut app| async move {
app.start_server();
PreparedApp::new,
|mut app| async {
app.start_server(&test_dir);
let page = app.new_page(browser).await;
page.wait_for_navigation().await.unwrap();
app.schedule_page_disposal(page);
// return the PreparedApp doesn't make dropping it part of the measurement
app
},
|app| app.dispose(),
)
);
remove_dir_all(&test_dir).unwrap();
});
}

g.finish();
}
struct PreparedApp {
server: Option<(Child, String)>,
test_dir: PathBuf,
pages: Vec<Page>,
}

impl PreparedApp {
async fn new(module_count: usize) -> Self {
let test_dir = TestAppBuilder {
module_count,
directories_count: module_count / 20,
..Default::default()
}
.build()
.unwrap();

async fn new() -> Self {
Self {
test_dir,
server: None,
pages: Vec::new(),
}
}

fn start_server(&mut self) {
fn start_server(&mut self, test_dir: &PathBuf) {
assert!(self.server.is_none(), "Server already started");

let mut proc = Command::new(std::env!("CARGO_BIN_EXE_next-dev"))
.args([self.test_dir.to_str().unwrap(), "--no-open", "--port", "0"])
.args([".", "--no-open", "--port", "0"])
.current_dir(test_dir)
.stdout(Stdio::piped())
.spawn()
.unwrap();
Expand All @@ -103,10 +95,34 @@ impl PreparedApp {
for page in self.pages {
page.close().await.unwrap();
}
remove_dir_all(&self.test_dir).unwrap();
}
}

fn build_test(module_count: usize) -> PathBuf {
let test_dir = TestAppBuilder {
module_count,
directories_count: module_count / 20,
package_json: true,
..Default::default()
}
.build()
.unwrap();

let npm = Command::new("npm")
.args(["install", "--prefer-offline", "--loglevel=error"])
.current_dir(&test_dir)
.output()
.unwrap();

if !npm.status.success() {
io::stdout().write_all(&npm.stdout).unwrap();
io::stderr().write_all(&npm.stderr).unwrap();
panic!("npm install failed. See above.");
}

test_dir
}

async fn create_browser() -> Browser {
let (browser, mut handler) = Browser::launch(BrowserConfig::builder().build().unwrap())
.await
Expand Down
2 changes: 1 addition & 1 deletion crates/turbopack-create-test-app/src/test_app_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ export function getStaticProps() {
"@next/react-refresh-utils": "^12.2.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-refresh": "^0.14.0",
"react-refresh": "^0.12.0",
}
};
File::create(path.join("package.json"))
Expand Down

0 comments on commit d3c8138

Please sign in to comment.