noirc_artifacts_info/
lib.rs1use acvm::acir::circuit::ExpressionWidth;
2use iter_extended::vecmap;
3use noirc_artifacts::program::ProgramArtifact;
4use prettytable::{Row, row, table};
5use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
6use serde::Serialize;
7
8#[derive(Debug, Default, Serialize)]
9pub struct InfoReport {
10 pub programs: Vec<ProgramInfo>,
11}
12
13#[derive(Debug, Serialize)]
14pub struct ProgramInfo {
15 pub package_name: String,
16 #[serde(skip)]
17 pub expression_width: Option<ExpressionWidth>,
18 pub functions: Vec<FunctionInfo>,
19 #[serde(skip)]
20 pub unconstrained_functions_opcodes: usize,
21 pub unconstrained_functions: Vec<FunctionInfo>,
22}
23
24impl From<ProgramInfo> for Vec<Row> {
25 fn from(program_info: ProgramInfo) -> Self {
26 let expression_width = if let Some(expression_width) = program_info.expression_width {
27 format!("{expression_width:?}")
28 } else {
29 "N/A".to_string()
30 };
31 let mut main = vecmap(program_info.functions, |function| {
32 row![
33 Fm->format!("{}", program_info.package_name),
34 Fc->format!("{}", function.name),
35 format!("{}", expression_width),
36 Fc->format!("{}", function.opcodes),
37 Fc->format!("{}", program_info.unconstrained_functions_opcodes),
38 ]
39 });
40 main.extend(vecmap(program_info.unconstrained_functions, |function| {
41 row![
42 Fm->format!("{}", program_info.package_name),
43 Fc->format!("{}", function.name),
44 format!("N/A", ),
45 Fc->format!("N/A"),
46 Fc->format!("{}", function.opcodes),
47 ]
48 }));
49 main
50 }
51}
52
53#[derive(Debug, Serialize)]
54pub struct FunctionInfo {
55 pub name: String,
56 pub opcodes: usize,
57}
58
59pub fn count_opcodes_and_gates_in_program(
60 compiled_program: ProgramArtifact,
61 package_name: String,
62 expression_width: Option<ExpressionWidth>,
63) -> ProgramInfo {
64 let functions = compiled_program
65 .bytecode
66 .functions
67 .into_par_iter()
68 .enumerate()
69 .map(|(i, function)| FunctionInfo {
70 name: compiled_program.names[i].clone(),
71 opcodes: function.opcodes.len(),
72 })
73 .collect();
74
75 let opcodes_len: Vec<usize> = compiled_program
76 .bytecode
77 .unconstrained_functions
78 .iter()
79 .map(|func| func.bytecode.len())
80 .collect();
81 let unconstrained_functions_opcodes = compiled_program
82 .bytecode
83 .unconstrained_functions
84 .into_par_iter()
85 .map(|function| function.bytecode.len())
86 .sum();
87 let unconstrained_info: Vec<FunctionInfo> = compiled_program
88 .brillig_names
89 .clone()
90 .iter()
91 .zip(opcodes_len)
92 .map(|(name, len)| FunctionInfo { name: name.clone(), opcodes: len })
93 .collect();
94
95 ProgramInfo {
96 package_name,
97 expression_width,
98 functions,
99 unconstrained_functions_opcodes,
100 unconstrained_functions: unconstrained_info,
101 }
102}
103
104pub fn show_info_report(info_report: InfoReport, json: bool) {
105 if json {
106 println!("{}", serde_json::to_string(&info_report).unwrap());
108 } else {
109 if !info_report.programs.is_empty() {
111 let mut program_table = table!([Fm->"Package", Fm->"Function", Fm->"Expression Width", Fm->"ACIR Opcodes", Fm->"Brillig Opcodes"]);
112
113 for program_info in info_report.programs {
114 let program_rows: Vec<Row> = program_info.into();
115 for row in program_rows {
116 program_table.add_row(row);
117 }
118 }
119 program_table.printstd();
120 }
121 }
122}