|
1 |
| -use chromiumoxide::browser::Browser; |
2 |
| -use futures_util::stream::StreamExt; |
| 1 | +pub mod run; |
3 | 2 | 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 |
| -}; |
12 | 3 |
|
13 |
| -const LOG_DIR: &str = "logs"; |
14 | 4 | const LOG_FILE_NAME: &str = "benchmark_noargs_logs.txt";
|
15 |
| -const SAMPLE_COUNT: u32 = 10; |
16 | 5 |
|
17 | 6 | #[tokio::main]
|
18 | 7 | async fn main() {
|
19 | 8 | set_var("CHROME_INIT", "ignore"); // Ignore the auto start.
|
20 | 9 | 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 |
160 | 11 | }
|
0 commit comments