|
22 | 22 | }, |
23 | 23 | }, |
24 | 24 | solana_stake_program::{get_minimum_delegation, id}, |
| 25 | + solana_svm_log_collector::LogCollector, |
25 | 26 | solana_sysvar_id::SysvarId, |
26 | 27 | solana_vote_interface::{ |
27 | 28 | program as vote_program, |
@@ -1123,3 +1124,89 @@ fn test_no_use_dealloc() { |
1123 | 1124 | } |
1124 | 1125 | } |
1125 | 1126 | } |
| 1127 | + |
| 1128 | +// this prints ballpark compute unit costs suitable for insertion in README.md |
| 1129 | +// run with `cargo test --test interface show_compute_usage -- --nocapture --ignored` |
| 1130 | +#[test] |
| 1131 | +#[ignore] |
| 1132 | +fn show_compute_usage() { |
| 1133 | + let mut env = Env::init(); |
| 1134 | + solana_logger::setup_with(""); |
| 1135 | + env.mollusk.logger = Some(LogCollector::new_ref()); |
| 1136 | + let mut compute_tracker = ComputeTracker::new(); |
| 1137 | + |
| 1138 | + for declaration in &*INSTRUCTION_DECLARATIONS { |
| 1139 | + let instruction = declaration.to_instruction(&mut env); |
| 1140 | + env.process_success(&instruction); |
| 1141 | + |
| 1142 | + let logs = env |
| 1143 | + .mollusk |
| 1144 | + .logger |
| 1145 | + .as_ref() |
| 1146 | + .unwrap() |
| 1147 | + .replace(LogCollector::default()) |
| 1148 | + .into_messages(); |
| 1149 | + |
| 1150 | + compute_tracker.add(&logs); |
| 1151 | + env.reset(); |
| 1152 | + } |
| 1153 | + |
| 1154 | + compute_tracker.show(); |
| 1155 | +} |
| 1156 | + |
| 1157 | +struct ComputeTracker(HashMap<String, u64>); |
| 1158 | +impl ComputeTracker { |
| 1159 | + fn new() -> Self { |
| 1160 | + Self(HashMap::from([("GetMinimumDelegation".to_string(), 0)])) |
| 1161 | + } |
| 1162 | + |
| 1163 | + fn add(&mut self, logs: &[String]) { |
| 1164 | + const IX_PREFIX: &str = "Program log: Instruction: "; |
| 1165 | + const CU_PREFIX: &str = "Program Stake11111111111111111111111111111111111111 consumed "; |
| 1166 | + |
| 1167 | + let instruction = logs |
| 1168 | + .iter() |
| 1169 | + .find_map(|line| { |
| 1170 | + line.strip_prefix(IX_PREFIX) |
| 1171 | + .map(|rest| rest.split_whitespace().next().unwrap().to_string()) |
| 1172 | + }) |
| 1173 | + .unwrap(); |
| 1174 | + |
| 1175 | + let compute_units = logs |
| 1176 | + .iter() |
| 1177 | + .find_map(|line| { |
| 1178 | + line.strip_prefix(CU_PREFIX).map(|rest| { |
| 1179 | + rest.split_whitespace() |
| 1180 | + .next() |
| 1181 | + .unwrap() |
| 1182 | + .parse::<u64>() |
| 1183 | + .unwrap() |
| 1184 | + }) |
| 1185 | + }) |
| 1186 | + .unwrap(); |
| 1187 | + |
| 1188 | + self.0 |
| 1189 | + .entry(instruction) |
| 1190 | + .and_modify(|v| *v = std::cmp::max(compute_units, *v)) |
| 1191 | + .or_insert(compute_units); |
| 1192 | + } |
| 1193 | + |
| 1194 | + fn show(&self) { |
| 1195 | + let mut instructions = self.0.keys().collect::<Vec<_>>(); |
| 1196 | + instructions.sort(); |
| 1197 | + |
| 1198 | + println!("\n| Instruction | Estimated Cost |"); |
| 1199 | + println!("| --- | --- |"); |
| 1200 | + |
| 1201 | + for instruction in instructions.into_iter() { |
| 1202 | + let compute_units = match self.0[instruction] { |
| 1203 | + n if n < 100 => "(negligible)".to_string(), |
| 1204 | + n => ((n + 50) / 100 * 100).to_string(), |
| 1205 | + }; |
| 1206 | + |
| 1207 | + println!("| `{}` | {} |", instruction, compute_units); |
| 1208 | + } |
| 1209 | + |
| 1210 | + println!(); |
| 1211 | + } |
| 1212 | +} |
0 commit comments