Skip to content

Commit

Permalink
[gas] add pretty texualization for transaction gas log and make gas p…
Browse files Browse the repository at this point in the history
…rofiling available in e2e move tests (#8689)
  • Loading branch information
vgao1996 authored Jun 30, 2023
1 parent 18bc643 commit 547ad67
Show file tree
Hide file tree
Showing 18 changed files with 1,144 additions and 351 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ __pycache__
aptos-move/aptos-vm-profiling/**/*.log
aptos-move/aptos-vm-profiling/**/*.txt

# Gas profiler outputs
aptos-move/e2e-move-tests/gas-profiling

# replay-verify and module-verify script outputs
metadata-cache
/local/
Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions aptos-move/aptos-gas-profiling/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rust-version = { workspace = true }
anyhow = { workspace = true }
inferno = { workspace = true }
regex = { workspace = true }
smallvec = { workspace = true }

aptos-framework = { workspace = true }
aptos-gas = { workspace = true }
Expand Down
129 changes: 129 additions & 0 deletions aptos-move/aptos-gas-profiling/src/aggregate.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright © Aptos Foundation
// SPDX-License-Identifier: Apache-2.0

use crate::{
log::{ExecutionAndIOCosts, ExecutionGasEvent},
render::{Render, TableKey},
};
use aptos_gas::{GasQuantity, GasScalingFactor, InternalGas};
use aptos_types::state_store::state_key::StateKeyInner;
use std::{
collections::{btree_map, BTreeMap},
ops::Deref,
};

/// Represents an aggregation of execution gas events, including the count and total gas costs for each type of event.
///
/// The events are sorted by the amount of gas used, from high to low.
pub struct AggregatedExecutionGasEvents {
/// The gas scaling factor.
/// This is included so to make this struct self-contained, suitable for displaying in (external) gas units.
pub gas_scaling_factor: GasScalingFactor,

/// The total gas cost.
pub total: InternalGas,

// TODO: Make this more strongly typed?
pub ops: Vec<(String, usize, InternalGas)>,
pub storage_reads: Vec<(String, usize, InternalGas)>,
pub storage_writes: Vec<(String, usize, InternalGas)>,
}

fn insert_or_add<K, U>(
map: &mut BTreeMap<K, (usize, GasQuantity<U>)>,
key: K,
amount: GasQuantity<U>,
) where
K: Ord,
{
if amount.is_zero() {
return;
}
match map.entry(key) {
btree_map::Entry::Occupied(entry) => {
let r = entry.into_mut();
r.0 += 1;
r.1 += amount;
},
btree_map::Entry::Vacant(entry) => {
entry.insert((1, amount));
},
}
}

fn into_sorted_vec<I, K, N>(collection: I) -> Vec<(K, usize, N)>
where
N: Ord,
I: IntoIterator<Item = (K, (usize, N))>,
{
let mut v = collection
.into_iter()
.map(|(key, (count, amount))| (key, count, amount))
.collect::<Vec<_>>();
// Sort in descending order.
v.sort_by(|(_key1, _count1, amount1), (_key2, _count2, amount2)| amount2.cmp(amount1));
v
}

impl ExecutionAndIOCosts {
/// Counts the number of hits and aggregates the gas costs for each type of event.
pub fn aggregate_gas_events(&self) -> AggregatedExecutionGasEvents {
use ExecutionGasEvent::*;

let mut ops = BTreeMap::new();
let mut storage_reads = BTreeMap::new();
let mut storage_writes = BTreeMap::new();

for event in self.gas_events() {
match event {
Loc(..) | Call(..) => (),
Bytecode { op, cost } => insert_or_add(
&mut ops,
format!("{:?}", op).to_ascii_lowercase().to_string(),
*cost,
),
CallNative {
module_id,
fn_name,
ty_args,
cost,
} => insert_or_add(
&mut ops,
format!(
"{}",
Render(&(module_id, fn_name.as_ident_str(), ty_args.as_slice())),
),
*cost,
),
LoadResource {
addr: _addr,
ty,
cost,
} => insert_or_add(&mut storage_reads, format!("{}", ty), *cost),
}
}

for write in &self.write_set_transient {
use StateKeyInner::*;

let key = match write.key.deref() {
AccessPath(ap) => format!("{}", Render(&ap.get_path())),
TableItem { handle, key } => {
format!("table_item<{},{}>", Render(handle), TableKey { bytes: key },)
},
Raw(..) => panic!("not supported"),
};

insert_or_add(&mut storage_writes, key, write.cost);
}

AggregatedExecutionGasEvents {
gas_scaling_factor: self.gas_scaling_factor,
total: self.total,

ops: into_sorted_vec(ops),
storage_reads: into_sorted_vec(storage_reads),
storage_writes: into_sorted_vec(storage_writes),
}
}
}
Loading

0 comments on commit 547ad67

Please sign in to comment.