1- use benchmarking_tool:: { CommandRequest , Entry , ToolOptions , ToolOutput , tools, utilities} ;
21use std:: collections:: HashMap ;
3- use utilities:: { Direction , Sorting } ;
2+ use std:: ffi:: OsString ;
3+ use std:: io:: Write ;
4+
5+ use benchmarking_tool:: { CommandRequest , Entry , ToolOptions , ToolOutput , tools, utilities} ;
6+ use utilities:: { Direction , PairedWriter , Sorting } ;
47
58fn main ( ) {
69 let mut args = std:: env:: args ( ) . skip ( 1 ) ;
@@ -9,15 +12,26 @@ fn main() {
912
1013 let input = BenchmarkInput :: from_arguments ( args) ;
1114
15+ let writer = PairedWriter :: new_from_option (
16+ input. write_to_stdout . then ( || std:: io:: stdout ( ) ) ,
17+ input. write_results_to . map ( |path| {
18+ let path = std:: path:: Path :: new ( & path) ;
19+ if let Some ( parent) = path. parent ( ) {
20+ std:: fs:: create_dir_all ( parent) . unwrap ( ) ;
21+ }
22+ std:: fs:: File :: create ( path) . unwrap ( )
23+ } ) ,
24+ ) ;
25+
1226 match tool {
1327 "--info" | "help" => {
1428 println ! ( "benchmarking-tool" ) ;
1529 println ! ( "run 'qbdi', 'sde', 'perf-events' or 'time'" ) ;
1630 }
1731 "qbdi" => {
1832 let request = CommandRequest {
19- program : input. program ,
20- arguments : input. arguments ,
33+ program : input. program . into ( ) ,
34+ arguments : input. arguments . into_iter ( ) . map ( Into :: into ) . collect ( ) ,
2135 } ;
2236 let options = ToolOptions {
2337 keep : input. keep ,
@@ -26,24 +40,26 @@ fn main() {
2640 let result = tools:: qbdi:: run_qbdi ( request, options) . unwrap ( ) ;
2741 match result {
2842 ToolOutput :: SymbolInstructionCounts { symbols, total } => print_results (
43+ & mut writer. expect ( "--quiet must have --write-results-to" ) ,
2944 symbols,
3045 total as usize ,
3146 input. format ,
3247 input. sort ,
3348 input. limit ,
3449 input. breakdown ,
35- ) ,
50+ )
51+ . unwrap ( ) ,
3652 _ => todo ! ( ) ,
3753 }
3854 }
3955 "time" => {
4056 todo ! ( )
4157 }
42- #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" ) ) ]
58+ #[ cfg( any( target_arch = "x86" , target_arch = "x86_64" , debug_assertions ) ) ]
4359 "sde" => {
4460 let request = CommandRequest {
45- program : input. program ,
46- arguments : input. arguments ,
61+ program : input. program . into ( ) ,
62+ arguments : input. arguments . into_iter ( ) . map ( Into :: into ) . collect ( ) ,
4763 } ;
4864 let options = ToolOptions {
4965 keep : input. keep ,
@@ -52,13 +68,15 @@ fn main() {
5268 let result = tools:: sde:: run_sde ( request, options) . unwrap ( ) ;
5369 match result {
5470 ToolOutput :: SymbolInstructionCounts { symbols, total } => print_results (
71+ & mut writer. expect ( "--quiet must have --write-results-to" ) ,
5572 symbols,
5673 total as usize ,
5774 input. format ,
5875 input. sort ,
5976 input. limit ,
6077 input. breakdown ,
61- ) ,
78+ )
79+ . unwrap ( ) ,
6280 _ => todo ! ( ) ,
6381 }
6482 }
@@ -88,8 +106,8 @@ pub struct BenchmarkInput {
88106 /// plain, JSON, markdown, csv
89107 pub format : OutputFormat ,
90108 // ...
91- pub program : String ,
92- pub arguments : Vec < String > ,
109+ pub program : OsString ,
110+ pub arguments : Vec < OsString > ,
93111 // ...
94112 pub generic_arguments : HashMap < String , Vec < String > > ,
95113
@@ -98,8 +116,11 @@ pub struct BenchmarkInput {
98116 pub keep : Option < String > ,
99117 /// skip Rust internals
100118 pub skip_internals : bool ,
101- /// include all inst
119+ /// include all instruction kinds
102120 pub breakdown : bool ,
121+ // things
122+ pub write_results_to : Option < String > ,
123+ pub write_to_stdout : bool ,
103124}
104125
105126impl BenchmarkInput {
@@ -109,14 +130,17 @@ impl BenchmarkInput {
109130 sort : None ,
110131 format : OutputFormat :: default ( ) ,
111132 // ...
112- program : String :: new ( ) ,
133+ program : OsString :: new ( ) ,
113134 arguments : Vec :: new ( ) ,
114135 // ...
115136 generic_arguments : HashMap :: new ( ) ,
116137 // ...
117138 keep : None ,
118139 skip_internals : true ,
119140 breakdown : false ,
141+ // ...
142+ write_results_to : None ,
143+ write_to_stdout : true ,
120144 } ;
121145
122146 let mut left_over: Option < String > = None ;
@@ -161,42 +185,55 @@ impl BenchmarkInput {
161185 "--keep" => {
162186 this. keep = args. next ( ) ;
163187 }
188+ "--write-results-to" => {
189+ this. write_results_to = args. next ( ) ;
190+ }
164191 "--all" => {
165192 this. skip_internals = false ;
166193 }
167194 "--breakdown" => {
168195 this. breakdown = true ;
169196 }
197+ "--quiet" => {
198+ this. write_to_stdout = false ;
199+ }
170200 "--arg" => {
201+ // `--arg name=6,7`
171202 let next = args. next ( ) . unwrap ( ) ;
172203 let ( name, values) = next. split_once ( '=' ) . unwrap ( ) ;
173- this. generic_arguments . insert (
174- name. to_owned ( ) ,
175- values. split ( ',' ) . map ( str:: to_owned) . collect ( ) ,
176- ) ;
204+ // TODO CSV parse?
205+ let values = values. trim ( ) . split ( ',' ) . map ( str:: to_owned) . collect ( ) ;
206+ this. generic_arguments . insert ( name. to_owned ( ) , values) ;
177207 }
178- // WIP
208+ // -- *program* *arg1* *arg2* ...
209+ "--" => {
210+ let arg = args. next ( ) . unwrap ( ) ;
211+ this. program = OsString :: from ( arg) ;
212+ break ;
213+ }
214+ // WIP. First unknown argument is the program
179215 _command => {
180- this. program = arg;
216+ this. program = OsString :: from ( arg) ;
181217 break ;
182218 }
183219 }
184220 }
185221
186- this. arguments = args. collect ( ) ;
222+ this. arguments = args. map ( OsString :: from ) . collect ( ) ;
187223
188224 this
189225 }
190226}
191227
192228pub fn print_results (
229+ to : & mut impl Write ,
193230 mut rows : Vec < Entry > ,
194231 total_count : usize ,
195232 output_format : OutputFormat ,
196233 sorting : Option < utilities:: Sorting > ,
197234 limit : usize ,
198235 breakdown : bool ,
199- ) {
236+ ) -> std :: io :: Result < ( ) > {
200237 use std:: borrow:: Cow ;
201238 use utilities:: count_with_seperator;
202239
@@ -218,7 +255,7 @@ pub fn print_results(
218255 rows. sort_unstable_by ( |lhs, rhs| sort. direction . compare ( & lhs. total , & rhs. total ) ) ;
219256 }
220257 field => {
221- eprintln ! ( " unknown field {field:?}") ;
258+ writeln ! ( to , "error: unknown field {field:?}") ? ;
222259 }
223260 }
224261 }
@@ -256,10 +293,11 @@ pub fn print_results(
256293 // println!();
257294 // }
258295
259- println ! (
296+ writeln ! (
297+ to,
260298 "Run {total} instructions" ,
261299 total = count_with_seperator( total_count as usize )
262- ) ;
300+ ) ? ;
263301 for row in rows {
264302 let symbol_name: Cow < ' _ , str > = if row. symbol_name . len ( ) > MAX_WIDTH {
265303 Cow :: Owned ( format ! (
@@ -272,21 +310,25 @@ pub fn print_results(
272310 let fill = & WHITESPACE [ ..max_name_width - symbol_name. len ( ) ] ;
273311
274312 // TODO wip
275- print ! ( "{symbol_name}{fill}" ) ;
276- print ! (
313+ write ! ( to, "{symbol_name}{fill}" ) ?;
314+ write ! (
315+ to,
277316 " total: {count}" ,
278317 count = count_with_seperator( row. total as usize )
279- ) ;
318+ ) ? ;
280319 if breakdown {
281320 for ( name, count) in & row. entries {
282- print ! (
321+ write ! (
322+ to,
283323 " {name}: {count}" ,
284324 count = count_with_seperator( * count as usize )
285- ) ;
325+ ) ? ;
286326 }
287327 }
288- println ! ( ) ;
328+ writeln ! ( to ) ? ;
289329 }
330+
331+ Ok ( ( ) )
290332 }
291333 OutputFormat :: JSON => {
292334 let mut buf = String :: from ( "[" ) ;
@@ -308,7 +350,7 @@ pub fn print_results(
308350 }
309351 }
310352 buf. push ( ']' ) ;
311- println ! ( "{buf}" ) ;
353+ write ! ( to , "{buf}" )
312354 }
313355 format => {
314356 todo ! ( "output format '{format:?}'" ) ;
0 commit comments