Skip to content

Commit fa550f0

Browse files
authored
add method-based tables to gas-profile (#17466)
Co-authored-by: Igor <[email protected]>
1 parent e977713 commit fa550f0

File tree

4 files changed

+127
-12
lines changed

4 files changed

+127
-12
lines changed

aptos-move/aptos-gas-profiling/src/aggregate.rs

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use crate::{
5+
erased::Node,
56
log::{ExecutionAndIOCosts, ExecutionGasEvent},
67
render::{Render, TableKey},
78
};
8-
use aptos_gas_algebra::{GasQuantity, GasScalingFactor, InternalGas};
9+
use aptos_gas_algebra::{GasQuantity, GasScalingFactor, InternalGas, InternalGasUnit};
910
use std::collections::{btree_map, BTreeMap};
1011

1112
/// Represents an aggregation of execution gas events, including the count and total gas costs for each type of event.
@@ -22,6 +23,8 @@ pub struct AggregatedExecutionGasEvents {
2223

2324
// TODO: Make this more strongly typed?
2425
pub ops: Vec<(String, usize, InternalGas)>,
26+
pub methods: Vec<(String, usize, InternalGas)>,
27+
pub methods_self: Vec<(String, usize, InternalGas)>,
2528
pub transaction_write: InternalGas,
2629
pub event_writes: Vec<(String, usize, InternalGas)>,
2730
pub storage_reads: Vec<(String, usize, InternalGas)>,
@@ -126,15 +129,55 @@ impl ExecutionAndIOCosts {
126129
insert_or_add(&mut storage_writes, key, write.cost);
127130
}
128131

132+
let tree = self.to_erased(false).tree;
133+
let mut methods = BTreeMap::new();
134+
compute_method_recursive_cost(&tree, &mut methods);
135+
let mut methods_self = BTreeMap::new();
136+
compute_method_self_cost(&tree, &mut methods_self);
137+
129138
AggregatedExecutionGasEvents {
130139
gas_scaling_factor: self.gas_scaling_factor,
131140
total: self.total,
132141

133142
ops: into_sorted_vec(ops),
143+
methods: into_sorted_vec(methods),
144+
methods_self: into_sorted_vec(methods_self),
134145
transaction_write: self.transaction_transient.unwrap_or_else(|| 0.into()),
135146
event_writes: into_sorted_vec(event_writes),
136147
storage_reads: into_sorted_vec(storage_reads),
137148
storage_writes: into_sorted_vec(storage_writes),
138149
}
139150
}
140151
}
152+
153+
fn compute_method_recursive_cost(
154+
node: &Node<GasQuantity<InternalGasUnit>>,
155+
methods: &mut BTreeMap<String, (usize, GasQuantity<InternalGasUnit>)>,
156+
) -> GasQuantity<InternalGasUnit> {
157+
let mut sum = node.val;
158+
for child in &node.children {
159+
sum += compute_method_recursive_cost(child, methods);
160+
}
161+
162+
if !node.children.is_empty() {
163+
insert_or_add(methods, node.text.clone(), sum);
164+
}
165+
sum
166+
}
167+
168+
fn compute_method_self_cost(
169+
node: &Node<GasQuantity<InternalGasUnit>>,
170+
methods: &mut BTreeMap<String, (usize, GasQuantity<InternalGasUnit>)>,
171+
) {
172+
let mut sum = node.val;
173+
for child in &node.children {
174+
compute_method_self_cost(child, methods);
175+
176+
// method invocation cost itself is counted to both parent and child.
177+
sum += child.val;
178+
}
179+
180+
if !node.children.is_empty() {
181+
insert_or_add(methods, node.text.clone(), sum);
182+
}
183+
}

aptos-move/aptos-gas-profiling/src/erased.rs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,13 +129,13 @@ impl<N> Node<N> {
129129
}
130130

131131
impl ExecutionGasEvent {
132-
fn to_erased(&self) -> Node<InternalGas> {
132+
fn to_erased(&self, keep_generic_types: bool) -> Node<InternalGas> {
133133
use ExecutionGasEvent::*;
134134

135135
match self {
136136
Loc(offset) => Node::new(format!("@{}", offset), 0),
137137
Bytecode { op, cost } => Node::new(format!("{:?}", op).to_ascii_lowercase(), *cost),
138-
Call(frame) => frame.to_erased(),
138+
Call(frame) => frame.to_erased(keep_generic_types),
139139
CallNative {
140140
module_id,
141141
fn_name,
@@ -144,7 +144,15 @@ impl ExecutionGasEvent {
144144
} => Node::new(
145145
format!(
146146
"{}",
147-
Render(&(module_id, fn_name.as_ident_str(), ty_args.as_slice()))
147+
Render(&(
148+
module_id,
149+
fn_name.as_ident_str(),
150+
if keep_generic_types {
151+
ty_args.as_slice()
152+
} else {
153+
&[]
154+
}
155+
))
148156
),
149157
*cost,
150158
),
@@ -158,7 +166,7 @@ impl ExecutionGasEvent {
158166
}
159167

160168
impl CallFrame {
161-
fn to_erased(&self) -> Node<InternalGas> {
169+
fn to_erased(&self, keep_generic_types: bool) -> Node<InternalGas> {
162170
let name = match &self.name {
163171
FrameName::Script => "script".to_string(),
164172
FrameName::Function {
@@ -168,15 +176,23 @@ impl CallFrame {
168176
} => {
169177
format!(
170178
"{}",
171-
Render(&(module_id, name.as_ident_str(), ty_args.as_slice()))
179+
Render(&(
180+
module_id,
181+
name.as_ident_str(),
182+
if keep_generic_types {
183+
ty_args.as_slice()
184+
} else {
185+
&[]
186+
}
187+
))
172188
)
173189
},
174190
};
175191

176192
let children = self
177193
.events
178194
.iter()
179-
.map(|event| event.to_erased())
195+
.map(|event| event.to_erased(keep_generic_types))
180196
.collect::<Vec<_>>();
181197

182198
Node::new_with_children(name, 0, children)
@@ -206,7 +222,7 @@ impl Dependency {
206222

207223
impl ExecutionAndIOCosts {
208224
/// Convert the gas log into a type-erased representation.
209-
pub fn to_erased(&self) -> TypeErasedExecutionAndIoCosts {
225+
pub fn to_erased(&self, keep_generic_types: bool) -> TypeErasedExecutionAndIoCosts {
210226
let mut nodes = vec![];
211227

212228
nodes.push(Node::new("intrinsic", self.intrinsic_cost));
@@ -222,7 +238,7 @@ impl ExecutionAndIOCosts {
222238
nodes.push(deps);
223239
}
224240

225-
nodes.push(self.call_graph.to_erased());
241+
nodes.push(self.call_graph.to_erased(keep_generic_types));
226242

227243
nodes.push(self.ledger_writes());
228244

@@ -297,9 +313,9 @@ impl StorageFees {
297313

298314
impl TransactionGasLog {
299315
/// Convert the gas log into a type-erased representation.
300-
pub fn to_erased(&self) -> TypeErasedGasLog {
316+
pub fn to_erased(&self, keep_generic_types: bool) -> TypeErasedGasLog {
301317
TypeErasedGasLog {
302-
exec_io: self.exec_io.to_erased(),
318+
exec_io: self.exec_io.to_erased(keep_generic_types),
303319
storage: self.storage.to_erased(),
304320
}
305321
}

aptos-move/aptos-gas-profiling/src/report.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ impl TransactionGasLog {
169169
"ops".to_string(),
170170
Value::Array(aggregated.ops.into_iter().map(convert_op).collect()),
171171
);
172+
data.insert(
173+
"methods".to_string(),
174+
Value::Array(aggregated.methods.into_iter().map(convert_op).collect()),
175+
);
176+
data.insert(
177+
"methods_self".to_string(),
178+
Value::Array(
179+
aggregated
180+
.methods_self
181+
.into_iter()
182+
.map(convert_op)
183+
.collect(),
184+
),
185+
);
172186
data.insert(
173187
"reads".to_string(),
174188
Value::Array(
@@ -301,7 +315,7 @@ impl TransactionGasLog {
301315
}
302316

303317
// Execution trace
304-
let mut tree = self.exec_io.to_erased().tree;
318+
let mut tree = self.exec_io.to_erased(true).tree;
305319
tree.include_child_costs();
306320

307321
let mut table = vec![];

aptos-move/aptos-gas-profiling/templates/index.html

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,48 @@ <h4>Execution</h4>
130130
{{else}}
131131
(No operations to show.)
132132
{{/if}}
133+
<br/>
134+
{{#if methods}}
135+
<table>
136+
<tr>
137+
<th><b>Methods (gas including children)</b></th>
138+
<th style="text-align: right"><b>Number of Hits</b></th>
139+
<th style="text-align: right"><b>Cost in Gas Units</b></th>
140+
<th style="text-align: right"><b>Percentage</b></th>
141+
</tr>
142+
{{#each methods}}
143+
<tr>
144+
<td>{{name}}</td>
145+
<td style="text-align: right">{{hits}}</td>
146+
<td style="text-align: right">{{cost}}</td>
147+
<td style="text-align: right">{{percentage}}</td>
148+
</tr>
149+
{{/each}}
150+
</table>
151+
{{else}}
152+
(No methods to show.)
153+
{{/if}}
154+
<br/>
155+
{{#if methods_self}}
156+
<table>
157+
<tr>
158+
<th><b>Methods (only local gas)</b></th>
159+
<th style="text-align: right"><b>Number of Hits</b></th>
160+
<th style="text-align: right"><b>Cost in Gas Units</b></th>
161+
<th style="text-align: right"><b>Percentage</b></th>
162+
</tr>
163+
{{#each methods_self}}
164+
<tr>
165+
<td>{{name}}</td>
166+
<td style="text-align: right">{{hits}}</td>
167+
<td style="text-align: right">{{cost}}</td>
168+
<td style="text-align: right">{{percentage}}</td>
169+
</tr>
170+
{{/each}}
171+
</table>
172+
{{else}}
173+
(No methods to show.)
174+
{{/if}}
133175
<h4>State Reads</h4>
134176
{{#if reads}}
135177
<table>

0 commit comments

Comments
 (0)