Skip to content

Commit d9ce54c

Browse files
committed
chore(benches): reuse main test
1 parent e094d0c commit d9ce54c

File tree

4 files changed

+179
-304
lines changed

4 files changed

+179
-304
lines changed

benches/NOTES.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Notes
2+
3+
Notes that can help with setting up the browser of choice.

benches/basic.rs

+2-153
Original file line numberDiff line numberDiff line change
@@ -1,161 +1,10 @@
1-
use chromiumoxide::browser::Browser;
2-
use futures_util::stream::StreamExt;
1+
pub mod run;
32
use std::env::set_var;
4-
use std::ops::Div;
5-
use std::{
6-
env,
7-
fs::{self, File, OpenOptions},
8-
io::{self, BufRead, Write},
9-
path::Path,
10-
time::{Duration, Instant},
11-
};
123

13-
const LOG_DIR: &str = "logs";
144
const LOG_FILE_NAME: &str = "benchmark_logs.txt";
15-
const SAMPLE_COUNT: u32 = 10;
165

176
#[tokio::main]
187
async fn main() {
198
set_var("CHROME_INIT", "ignore"); // Ignore the auto start.
20-
ensure_log_directory_exists(LOG_DIR).expect("Failed to create log directory");
21-
let query = env::var("BENCH_URL").unwrap_or_else(|_| "http://spider.cloud".into());
22-
let mut total_duration = Duration::new(0, 0);
23-
24-
headless_browser_lib::fork(Some(*headless_browser_lib::conf::DEFAULT_PORT)).await;
25-
tokio::spawn(headless_browser_lib::run_main());
26-
tokio::time::sleep(Duration::from_millis(1000)).await; // Wait for the server to load.
27-
28-
for i in 0..SAMPLE_COUNT {
29-
println!("Running sample {} of {}", i + 1, SAMPLE_COUNT);
30-
31-
let start_time = Instant::now();
32-
let result = navigate_extract_and_close(&query).await;
33-
let duration = start_time.elapsed();
34-
35-
if let Err(e) = result {
36-
eprintln!("Error running test {}: {:?}", i + 1, e);
37-
} else {
38-
println!("Sample {} took: {:?}", i + 1, duration);
39-
}
40-
41-
total_duration += duration;
42-
}
43-
44-
let average_duration = total_duration.div(SAMPLE_COUNT);
45-
println!("Finished average time: {:?}", average_duration);
46-
log_performance(average_duration, &query).expect("Failed to log performance");
47-
}
48-
49-
fn ensure_log_directory_exists(dir: &str) -> io::Result<()> {
50-
if !Path::new(dir).exists() {
51-
fs::create_dir_all(dir)?;
52-
}
53-
Ok(())
54-
}
55-
56-
fn log_performance(current_avg: Duration, query: &str) -> io::Result<()> {
57-
let os_type = sys_info::os_type().unwrap_or_default();
58-
let cpu_count = sys_info::cpu_num().unwrap_or_default().to_string();
59-
let sanitized_os = os_type.replace(|c: char| !c.is_alphanumeric(), "_");
60-
61-
// Construct the log file path with the machine information
62-
let log_file_name = format!("{}_v{}cpu_{}", sanitized_os, cpu_count, LOG_FILE_NAME);
63-
let log_file_path = format!("{}/{}", LOG_DIR, log_file_name);
64-
65-
if let Ok(mut log_file) = OpenOptions::new()
66-
.read(true)
67-
.write(true)
68-
.append(true)
69-
.create(true)
70-
.open(log_file_path)
71-
{
72-
let chrome_args = format!(
73-
"({})({:?})",
74-
headless_browser_lib::conf::CHROME_ARGS.len(),
75-
headless_browser_lib::conf::CHROME_ARGS.join(",")
76-
);
77-
let chrome_path = headless_browser_lib::conf::CHROME_PATH
78-
.trim_end_matches('/')
79-
.to_string();
80-
let chrome_path = Path::new(&chrome_path)
81-
.file_name()
82-
.and_then(|s| s.to_str())
83-
.unwrap_or_default();
84-
85-
let last_benchmark = get_last_benchmark(&log_file)?;
86-
87-
if let Some(last_avg) = last_benchmark {
88-
match current_avg.cmp(&last_avg) {
89-
std::cmp::Ordering::Greater => {
90-
println!("Performance degraded. Previous average: {:?}", last_avg)
91-
}
92-
std::cmp::Ordering::Less => {
93-
println!("Performance improved. Previous average: {:?}", last_avg)
94-
}
95-
std::cmp::Ordering::Equal => println!("Performance unchanged."),
96-
}
97-
}
98-
99-
writeln!(
100-
log_file,
101-
"<{query}> - {SAMPLE_COUNT} SAMPLES\nCHROME_PATH: {}\nCHROME_ARGS: {}\nMACHINE: {}\nDATE: {}\nAverage Duration: {:?}\n",
102-
chrome_path,
103-
chrome_args,
104-
format!("{}/v{}cpu", os_type, cpu_count),
105-
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
106-
current_avg
107-
)?;
108-
}
109-
Ok(())
110-
}
111-
112-
fn get_last_benchmark(log_file: &File) -> io::Result<Option<Duration>> {
113-
let mut lines = io::BufReader::new(log_file).lines();
114-
let mut last_line = None;
115-
while let Some(line) = lines.next() {
116-
last_line = Some(line?);
117-
}
118-
119-
if let Some(last_line) = last_line {
120-
if let Some(duration_str) = last_line.split(',').next() {
121-
if let Some(duration_value) = duration_str.split(':').nth(1) {
122-
return Ok(Some(parse_duration(duration_value.trim())?));
123-
}
124-
}
125-
}
126-
Ok(None)
127-
}
128-
129-
fn parse_duration(s: &str) -> io::Result<Duration> {
130-
if let Some(stripped) = s.strip_suffix("ms") {
131-
stripped
132-
.parse::<f64>()
133-
.map(|millis| Duration::from_millis(millis as u64))
134-
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid duration format"))
135-
} else {
136-
Err(io::Error::new(
137-
io::ErrorKind::InvalidData,
138-
"Invalid duration format",
139-
))
140-
}
141-
}
142-
143-
async fn navigate_extract_and_close(u: &str) -> Result<(), Box<dyn std::error::Error>> {
144-
let (browser, mut handler) =
145-
Browser::connect_with_config("http://127.0.0.1:6000/json/version", Default::default())
146-
.await?;
147-
148-
let handle = tokio::task::spawn(async move {
149-
while let Some(h) = handler.next().await {
150-
if h.is_err() {
151-
break;
152-
}
153-
}
154-
});
155-
156-
let page = browser.new_page(u).await?;
157-
page.wait_for_navigation().await?.content().await?;
158-
handle.abort(); // Abort the handle to drop the connection.
159-
160-
Ok(())
9+
run::run(LOG_FILE_NAME).await
16110
}

benches/basic_no_args.rs

+2-151
Original file line numberDiff line numberDiff line change
@@ -1,160 +1,11 @@
1-
use chromiumoxide::browser::Browser;
2-
use futures_util::stream::StreamExt;
1+
pub mod run;
32
use std::env::set_var;
4-
use std::ops::Div;
5-
use std::{
6-
env,
7-
fs::{self, File, OpenOptions},
8-
io::{self, BufRead, Write},
9-
path::Path,
10-
time::{Duration, Instant},
11-
};
123

13-
const LOG_DIR: &str = "logs";
144
const LOG_FILE_NAME: &str = "benchmark_noargs_logs.txt";
15-
const SAMPLE_COUNT: u32 = 10;
165

176
#[tokio::main]
187
async fn main() {
198
set_var("CHROME_INIT", "ignore"); // Ignore the auto start.
209
set_var("TEST_NO_ARGS", "true");
21-
ensure_log_directory_exists(LOG_DIR).expect("Failed to create log directory");
22-
let query = env::var("BENCH_URL").unwrap_or_else(|_| "http://spider.cloud".into());
23-
let mut total_duration = Duration::new(0, 0);
24-
25-
headless_browser_lib::fork(Some(*headless_browser_lib::conf::DEFAULT_PORT)).await;
26-
tokio::spawn(headless_browser_lib::run_main());
27-
tokio::time::sleep(Duration::from_millis(1000)).await; // Wait for the server to load.
28-
29-
for i in 0..SAMPLE_COUNT {
30-
println!("Running sample {} of {}", i + 1, SAMPLE_COUNT);
31-
32-
let start_time = Instant::now();
33-
let result = navigate_extract_and_close(&query).await;
34-
let duration = start_time.elapsed();
35-
36-
if let Err(e) = result {
37-
eprintln!("Error running test {}: {:?}", i + 1, e);
38-
} else {
39-
println!("Sample {} took: {:?}", i + 1, duration);
40-
}
41-
42-
total_duration += duration;
43-
}
44-
45-
let average_duration = total_duration.div(SAMPLE_COUNT);
46-
println!("Finished average time: {:?}", average_duration);
47-
log_performance(average_duration, &query).expect("Failed to log performance");
48-
}
49-
50-
fn ensure_log_directory_exists(dir: &str) -> io::Result<()> {
51-
if !Path::new(dir).exists() {
52-
fs::create_dir_all(dir)?;
53-
}
54-
Ok(())
55-
}
56-
57-
fn log_performance(current_avg: Duration, query: &str) -> io::Result<()> {
58-
let os_type = sys_info::os_type().unwrap_or_default();
59-
let cpu_count = sys_info::cpu_num().unwrap_or_default().to_string();
60-
let sanitized_os = os_type.replace(|c: char| !c.is_alphanumeric(), "_");
61-
62-
// Construct the log file path with the machine information
63-
let log_file_name = format!("{}_v{}cpu_{}", sanitized_os, cpu_count, LOG_FILE_NAME);
64-
let log_file_path = format!("{}/{}", LOG_DIR, log_file_name);
65-
66-
if let Ok(mut log_file) = OpenOptions::new()
67-
.read(true)
68-
.write(true)
69-
.append(true)
70-
.create(true)
71-
.open(log_file_path)
72-
{
73-
let chrome_args = format!(
74-
"({})({:?})",
75-
headless_browser_lib::conf::CHROME_ARGS_TEST.len(),
76-
headless_browser_lib::conf::CHROME_ARGS_TEST.join(",")
77-
);
78-
let chrome_path = headless_browser_lib::conf::CHROME_PATH
79-
.trim_end_matches('/')
80-
.to_string();
81-
let chrome_path = Path::new(&chrome_path)
82-
.file_name()
83-
.and_then(|s| s.to_str())
84-
.unwrap_or_default();
85-
let last_benchmark = get_last_benchmark(&log_file)?;
86-
87-
if let Some(last_avg) = last_benchmark {
88-
match current_avg.cmp(&last_avg) {
89-
std::cmp::Ordering::Greater => {
90-
println!("Performance degraded. Previous average: {:?}", last_avg)
91-
}
92-
std::cmp::Ordering::Less => {
93-
println!("Performance improved. Previous average: {:?}", last_avg)
94-
}
95-
std::cmp::Ordering::Equal => println!("Performance unchanged."),
96-
}
97-
}
98-
99-
writeln!(
100-
log_file,
101-
"<{query}> - {SAMPLE_COUNT} SAMPLES\nCHROME_PATH: {}\nCHROME_ARGS: {}\nMACHINE: {}\nDATE: {}\nAverage Duration: {:?}\n",
102-
chrome_path,
103-
chrome_args,
104-
format!("{}/v{}cpu", os_type, cpu_count),
105-
chrono::Local::now().format("%Y-%m-%d %H:%M:%S"),
106-
current_avg
107-
)?;
108-
}
109-
Ok(())
110-
}
111-
112-
fn get_last_benchmark(log_file: &File) -> io::Result<Option<Duration>> {
113-
let mut lines = io::BufReader::new(log_file).lines();
114-
let mut last_line = None;
115-
while let Some(line) = lines.next() {
116-
last_line = Some(line?);
117-
}
118-
119-
if let Some(last_line) = last_line {
120-
if let Some(duration_str) = last_line.split(',').next() {
121-
if let Some(duration_value) = duration_str.split(':').nth(1) {
122-
return Ok(Some(parse_duration(duration_value.trim())?));
123-
}
124-
}
125-
}
126-
Ok(None)
127-
}
128-
129-
fn parse_duration(s: &str) -> io::Result<Duration> {
130-
if let Some(stripped) = s.strip_suffix("ms") {
131-
stripped
132-
.parse::<f64>()
133-
.map(|millis| Duration::from_millis(millis as u64))
134-
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid duration format"))
135-
} else {
136-
Err(io::Error::new(
137-
io::ErrorKind::InvalidData,
138-
"Invalid duration format",
139-
))
140-
}
141-
}
142-
async fn navigate_extract_and_close(u: &str) -> Result<(), Box<dyn std::error::Error>> {
143-
let (browser, mut handler) =
144-
Browser::connect_with_config("http://127.0.0.1:6000/json/version", Default::default())
145-
.await?;
146-
147-
let handle = tokio::task::spawn(async move {
148-
while let Some(h) = handler.next().await {
149-
if h.is_err() {
150-
break;
151-
}
152-
}
153-
});
154-
155-
let page = browser.new_page(u).await?;
156-
page.wait_for_navigation().await?.content().await?;
157-
handle.abort(); // Abort the handle to drop the connection.
158-
159-
Ok(())
10+
run::run(LOG_FILE_NAME).await
16011
}

0 commit comments

Comments
 (0)