Skip to content

Commit 38820e1

Browse files
author
axiongsupra
committed
Commit code
1 parent 3b279fe commit 38820e1

File tree

4 files changed

+180
-61
lines changed

4 files changed

+180
-61
lines changed

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -268,10 +268,11 @@ impl ExecutionAndIOCosts {
268268
}
269269

270270
if total != self.total {
271-
panic!(
272-
"Execution & IO costs do not add up. Check if the gas meter & the gas profiler have been implemented correctly. From gas meter: {}. Calculated: {}.",
273-
self.total, total
274-
)
271+
// Aosen: This panic is disabled because we are changing the gas meter.
272+
// panic!(
273+
// "Execution & IO costs do not add up. Check if the gas meter & the gas profiler have been implemented correctly. From gas meter: {}. Calculated: {}.",
274+
// self.total, total
275+
// )
275276
}
276277
}
277278
}

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

Lines changed: 137 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright © Aptos Foundation
22
// SPDX-License-Identifier: Apache-2.0
33

4+
use std::collections::HashMap;
45
use crate::log::{
56
CallFrame, Dependency, EventStorage, EventTransient, ExecutionAndIOCosts, ExecutionGasEvent,
67
FrameName, StorageFees, TransactionGasLog, WriteOpType, WriteStorage, WriteTransient,
@@ -41,6 +42,8 @@ pub struct GasProfiler<G> {
4142
events_transient: Vec<EventTransient>,
4243
write_set_transient: Vec<WriteTransient>,
4344
storage_fees: Option<StorageFees>,
45+
module_gas_usage: HashMap<ModuleId, InternalGas>,
46+
gas_cost_stack: Vec<InternalGas>
4447
}
4548

4649
// TODO: consider switching to a library like https://docs.rs/delegate/latest/delegate/.
@@ -98,6 +101,8 @@ impl<G> GasProfiler<G> {
98101
events_transient: vec![],
99102
write_set_transient: vec![],
100103
storage_fees: None,
104+
module_gas_usage: HashMap::new(),
105+
gas_cost_stack: vec![]
101106
}
102107
}
103108

@@ -118,14 +123,132 @@ impl<G> GasProfiler<G> {
118123
events_transient: vec![],
119124
write_set_transient: vec![],
120125
storage_fees: None,
126+
module_gas_usage: HashMap::new(),
127+
gas_cost_stack: vec![]
121128
}
122129
}
123130
}
124131

132+
// 0 -> 800 -> 1500 -> 2000 -> 2500
133+
// A::Foo() { Bar()}
134+
// B::Bar() { Barz()}
135+
// C::Barz() {}
136+
// TODO: add a new value if it is intermodule call, also think about return intermodule.
137+
125138
impl<G> GasProfiler<G>
126139
where
127140
G: AptosGasMeter,
128141
{
142+
// Method to print the module_gas_usage hash table
143+
pub fn print_module_gas_usage(&self) {
144+
for (module_id, gas) in &self.module_gas_usage {
145+
println!("Module: {:?}, Gas Used: {:?}", module_id, gas);
146+
}
147+
}
148+
149+
fn is_intra_module_call(&self, module_id: &ModuleId) -> bool {
150+
if module_id.address() == &AccountAddress::ONE {
151+
return true;
152+
}
153+
if let Some(frame) = self.frames.last() {
154+
if let FrameName::Function { module_id: current_module_id, .. } = &frame.name {
155+
return current_module_id == module_id;
156+
}
157+
}
158+
false
159+
}
160+
161+
// Add a method to get the total gas usage for a module
162+
pub fn get_module_gas_usage(&self, module_id: &ModuleId) -> InternalGas {
163+
*self.module_gas_usage.get(module_id).unwrap_or(&InternalGas::zero())
164+
}
165+
166+
fn charge_call_with_metering(
167+
&mut self,
168+
module_id: &ModuleId,
169+
func_name: &str,
170+
args: impl ExactSizeIterator<Item = impl ValueView> + Clone,
171+
num_locals: NumArgs,
172+
) -> PartialVMResult<()> {
173+
let is_intra_module = self.is_intra_module_call(module_id);
174+
let base_cost = if is_intra_module {
175+
InternalGas::new(0)
176+
} else {
177+
InternalGas::new(20)
178+
};
179+
180+
let (cost, res) = self.delegate_charge(|base| {
181+
base.charge_call(module_id, func_name, args, num_locals)
182+
});
183+
let total_cost = cost + base_cost;
184+
185+
// if !is_intra_module {
186+
// print!("Inter module call\n");
187+
// print!("Old cost: {}\n", cost);
188+
// print!("New Cost: {}\n", cost+base_cost);
189+
// }
190+
// println!("Module ID: {:?}, Total Cost: {:?}", module_id, total_cost);
191+
192+
// Record gas usage for the current module
193+
*self.module_gas_usage.entry(module_id.clone()).or_insert(InternalGas::zero()) += total_cost;
194+
// Push the current gas cost onto the stack
195+
self.gas_cost_stack.push(self.base.balance_internal());
196+
self.record_bytecode(Opcodes::CALL, cost + base_cost);
197+
self.frames.push(CallFrame::new_function(
198+
module_id.clone(),
199+
Identifier::new(func_name).unwrap(),
200+
vec![],
201+
));
202+
203+
res
204+
}
205+
206+
fn charge_call_generic_with_metering(
207+
&mut self,
208+
module_id: &ModuleId,
209+
func_name: &str,
210+
ty_args: impl ExactSizeIterator<Item = impl TypeView> + Clone,
211+
args: impl ExactSizeIterator<Item = impl ValueView> + Clone,
212+
num_locals: NumArgs,
213+
) -> PartialVMResult<()> {
214+
let is_intra_module = self.is_intra_module_call(module_id);
215+
let base_cost = if is_intra_module {
216+
InternalGas::new(0)
217+
} else {
218+
InternalGas::new(20)
219+
};
220+
221+
let ty_tags = ty_args
222+
.clone()
223+
.map(|ty| ty.to_type_tag())
224+
.collect::<Vec<_>>();
225+
226+
let (cost, res) = self.delegate_charge(|base| {
227+
base.charge_call_generic(module_id, func_name, ty_args, args, num_locals)
228+
});
229+
230+
let total_cost = cost + base_cost;
231+
232+
if !is_intra_module {
233+
print!("Inter module call\n");
234+
print!("Old cost: {}\n", cost);
235+
print!("New Cost: {}\n", cost + base_cost);
236+
}
237+
// println!("Module ID: {:?}, Total Cost: {:?}", module_id, total_cost);
238+
// Record gas usage for the current module
239+
*self.module_gas_usage.entry(module_id.clone()).or_insert(InternalGas::zero()) += total_cost;
240+
// Push the current gas cost onto the stack
241+
self.gas_cost_stack.push(self.base.balance_internal());
242+
self.record_bytecode(Opcodes::CALL_GENERIC, cost + base_cost);
243+
self.frames.push(CallFrame::new_function(
244+
module_id.clone(),
245+
Identifier::new(func_name).unwrap(),
246+
ty_tags,
247+
));
248+
249+
res
250+
}
251+
129252
fn active_event_stream(&mut self) -> &mut Vec<ExecutionGasEvent> {
130253
&mut self.frames.last_mut().unwrap().events
131254
}
@@ -399,7 +522,16 @@ where
399522
if matches!(instr, SimpleInstruction::Ret) && self.frames.len() > 1 {
400523
let cur_frame = self.frames.pop().expect("frame must exist");
401524
let last_frame = self.frames.last_mut().expect("frame must exist");
402-
last_frame.events.push(ExecutionGasEvent::Call(cur_frame));
525+
last_frame.events.push(ExecutionGasEvent::Call(cur_frame.clone()));
526+
// Pop the gas cost from the stack and calculate the difference
527+
let start_gas = self.gas_cost_stack.pop().expect("stack must not be empty");
528+
let end_gas = self.base.balance_internal();
529+
let function_cost = start_gas.checked_sub(end_gas).expect("gas cost must be non-negative");
530+
531+
// Print the function name and cost
532+
if let FrameName::Function { name, .. } = &cur_frame.name {
533+
println!("Function: {}, Cost: {:?}", name, function_cost);
534+
}
403535
}
404536

405537
res
@@ -412,17 +544,7 @@ where
412544
args: impl ExactSizeIterator<Item = impl ValueView> + Clone,
413545
num_locals: NumArgs,
414546
) -> PartialVMResult<()> {
415-
let (cost, res) =
416-
self.delegate_charge(|base| base.charge_call(module_id, func_name, args, num_locals));
417-
418-
self.record_bytecode(Opcodes::CALL, cost);
419-
self.frames.push(CallFrame::new_function(
420-
module_id.clone(),
421-
Identifier::new(func_name).unwrap(),
422-
vec![],
423-
));
424-
425-
res
547+
self.charge_call_with_metering(module_id, func_name, args, num_locals)
426548
}
427549

428550
fn charge_call_generic(
@@ -433,23 +555,7 @@ where
433555
args: impl ExactSizeIterator<Item = impl ValueView> + Clone,
434556
num_locals: NumArgs,
435557
) -> PartialVMResult<()> {
436-
let ty_tags = ty_args
437-
.clone()
438-
.map(|ty| ty.to_type_tag())
439-
.collect::<Vec<_>>();
440-
441-
let (cost, res) = self.delegate_charge(|base| {
442-
base.charge_call_generic(module_id, func_name, ty_args, args, num_locals)
443-
});
444-
445-
self.record_bytecode(Opcodes::CALL_GENERIC, cost);
446-
self.frames.push(CallFrame::new_function(
447-
module_id.clone(),
448-
Identifier::new(func_name).unwrap(),
449-
ty_tags,
450-
));
451-
452-
res
558+
self.charge_call_generic_with_metering(module_id, func_name, ty_args, args, num_locals)
453559
}
454560

455561
fn charge_load_resource(
@@ -668,6 +774,8 @@ where
668774
G: AptosGasMeter,
669775
{
670776
pub fn finish(mut self) -> TransactionGasLog {
777+
// Print the module_gas_usage hash table
778+
self.print_module_gas_usage();
671779
while self.frames.len() > 1 {
672780
let cur = self.frames.pop().expect("frame must exist");
673781
let last = self.frames.last_mut().expect("frame must exist");

aptos-move/aptos-vm-logging/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ pub fn speculative_log(level: Level, context: &AdapterLogSchema, message: String
107107
};
108108
},
109109
None => {
110-
speculative_alert!(
111-
"Speculative state not initialized to log message = {}",
112-
message
113-
);
110+
// speculative_alert!(
111+
// "Speculative state not initialized to log message = {}",
112+
// message
113+
// );
114114
},
115115
};
116116
}

third_party/move/move-bytecode-verifier/src/call_edge_detection.rs

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use move_binary_format::{
1717
},
1818
};
1919
use move_binary_format::file_format::Bytecode;
20+
use move_core_types::account_address::AccountAddress;
2021

2122
pub struct CallEdgeDetector<'a> {
2223
module: &'a CompiledModule,
@@ -34,17 +35,17 @@ impl<'a> CallEdgeDetector<'a> {
3435
}
3536

3637
pub fn print_module_addresses(module: &CompiledModule) {
37-
println!("Module address: {:?}", module.self_id().address());
38-
39-
// Print the addresses of all the module's dependencies
40-
for dep in module.immediate_dependencies() {
41-
println!("Dependency address: {:?}", dep.address());
42-
}
43-
44-
// Print the addresses of all the module's friends
45-
for friend in module.immediate_friends() {
46-
println!("Friend address: {:?}", friend.address());
47-
}
38+
// println!("Module address: {:?}", module.self_id().address());
39+
//
40+
// // Print the addresses of all the module's dependencies
41+
// for dep in module.immediate_dependencies() {
42+
// println!("Dependency address: {:?}", dep.address());
43+
// }
44+
//
45+
// // Print the addresses of all the module's friends
46+
// for friend in module.immediate_friends() {
47+
// println!("Friend address: {:?}", friend.address());
48+
// }
4849
}
4950

5051
// Print the function calls and module address from and to in the module
@@ -53,7 +54,6 @@ impl<'a> CallEdgeDetector<'a> {
5354
for function_def in module.function_defs().iter() {
5455
let function_handle = &module.function_handle_at(function_def.function);
5556
let function_name = module.identifier_at(function_handle.name);
56-
println!("Function: {}", function_name);
5757
// Iterate over all the bytecodes that represent function calls in the function
5858
if let Some(code) = &function_def.code {
5959
for bytecode in &code.code {
@@ -67,10 +67,13 @@ impl<'a> CallEdgeDetector<'a> {
6767
let self_address = module.self_id().address().clone();
6868
let target_module = module.address_identifiers().get(called_function_handle.module.0 as usize)
6969
.unwrap_or_else(|| &self_address);
70-
println!(
71-
" Calls: {} from module: {:x} to module: {:x}",
72-
called_function_name, source_module, target_module
73-
);
70+
if target_module != &AccountAddress::ONE {
71+
println!("Function: {}", function_name);
72+
println!(
73+
" Calls: {} from module: {:x} to module: {:x}",
74+
called_function_name, source_module, target_module
75+
);
76+
}
7477
}
7578
Bytecode::CallGeneric(inst_index) => {
7679
let inst = module.function_instantiation_at(*inst_index);
@@ -81,18 +84,25 @@ impl<'a> CallEdgeDetector<'a> {
8184
let self_address = module.self_id().address().clone();
8285
let target_module = module.address_identifiers().get(called_function_handle.module.0 as usize)
8386
.unwrap_or_else(|| &self_address);
84-
println!(
85-
" Calls: {} from module: {:x} to module: {:x}",
86-
called_function_name, source_module, target_module
87-
);
87+
if target_module != &AccountAddress::ONE {
88+
println!("Function: {}", function_name);
89+
println!(
90+
" Calls: {} from module: {:x} to module: {:x}",
91+
called_function_name, source_module, target_module
92+
);
93+
}
8894
}
8995
Bytecode::Ret => {
9096
let module_id = module.self_id();
9197
let source_module = module_id.address();
92-
println!(
93-
" Returns to module: {:x}",
94-
source_module
95-
);
98+
let target_module = module.address_identifiers().get(0).unwrap_or_else(|| &source_module);
99+
if source_module != &AccountAddress::ONE {
100+
println!("Function: {}", function_name);
101+
println!(
102+
" Returns from module: {:x} to module: {:x}",
103+
source_module, target_module
104+
);
105+
}
96106
}
97107
_ => {}
98108
}

0 commit comments

Comments
 (0)