Skip to content

Commit

Permalink
optimization try-2 + benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
agryaznov committed Nov 14, 2022
1 parent b2b0b9d commit e7b35c0
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 8 deletions.
92 changes: 92 additions & 0 deletions BENCHMARKS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# Benchmarks

## Table of Contents

- [Benchmark Results](#benchmark-results)
- [Coremark, instrumented](#coremark,-instrumented)
- [recursive_ok, instrumented](#recursive_ok,-instrumented)
- [fibonacci_recursive, instrumented](#fibonacci_recursive,-instrumented)
- [factorial_recursive, instrumented](#factorial_recursive,-instrumented)
- [count_until, instrumented](#count_until,-instrumented)
- [memory_vec_add, instrumented](#memory_vec_add,-instrumented)
- [wasm_kernel::tiny_keccak, instrumented](#wasm_kernel::tiny_keccak,-instrumented)
- [global_bump, instrumented](#global_bump,-instrumented)

## Instrumented Modules sizes

| fixture | original size | gas metered/host fn | gas metered/mut global | size diff |
|------------------------------|------------------|---------------------|------------------------|-----------|
| many_blocks.wasm | 1023 kb | 2389 kb (233%) | 4778 kb (466%) | +99% |
| recursive_ok.wat | 0 kb | 0 kb (137%) | 0 kb (207%) | +50% |
| count_until.wat | 0 kb | 0 kb (125%) | 0 kb (174%) | +38% |
| factorial.wat | 0 kb | 0 kb (125%) | 0 kb (173%) | +38% |
| global_bump.wat | 0 kb | 0 kb (123%) | 0 kb (164%) | +33% |
| fibonacci.wat | 0 kb | 0 kb (121%) | 0 kb (159%) | +31% |
| memory-vec-add.wat | 0 kb | 0 kb (116%) | 0 kb (147%) | +26% |
| coremark_minimal.wasm | 7 kb | 8 kb (114%) | 10 kb (140%) | +22% |
| contract_transfer.wasm | 7 kb | 8 kb (113%) | 10 kb (136%) | +20% |
| erc1155.wasm | 26 kb | 29 kb (111%) | 34 kb (130%) | +17% |
| multisig.wasm | 27 kb | 30 kb (110%) | 35 kb (128%) | +16% |
| contract_terminate.wasm | 1 kb | 1 kb (110%) | 1 kb (128%) | +16% |
| rand_extension.wasm | 4 kb | 5 kb (109%) | 6 kb (125%) | +14% |
| proxy.wasm | 3 kb | 4 kb (108%) | 4 kb (124%) | +14% |
| trait_erc20.wasm | 10 kb | 11 kb (108%) | 12 kb (123%) | +13% |
| erc20.wasm | 9 kb | 10 kb (108%) | 12 kb (123%) | +13% |
| dns.wasm | 10 kb | 11 kb (108%) | 12 kb (122%) | +13% |
| erc721.wasm | 13 kb | 14 kb (108%) | 16 kb (123%) | +13% |
| wasm_kernel.wasm | 779 kb | 787 kb (100%) | 847 kb (108%) | +7% |


## Benchmark Results

### Coremark, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `19.16 s` (✅ **1.00x**) | `17.23 s` (✅ **1.11x faster**) |

### recursive_ok, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `408.70 us` (✅ **1.00x**) | `742.90 us` (❌ *1.82x slower*) |

### fibonacci_recursive, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `11.70 us` (✅ **1.00x**) | `19.63 us` (❌ *1.68x slower*) |

### factorial_recursive, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `1.57 us` (✅ **1.00x**) | `2.54 us` (❌ *1.62x slower*) |

### count_until, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `5.60 ms` (✅ **1.00x**) | `10.35 ms` (❌ *1.85x slower*) |

### memory_vec_add, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `8.77 ms` (✅ **1.00x**) | `13.18 ms` (❌ *1.50x slower*) |

### wasm_kernel::tiny_keccak, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `1.32 ms` (✅ **1.00x**) | `1.53 ms` (❌ *1.16x slower*) |

### global_bump, instrumented

| | `with host_function::Injector` | `with mutable_global::Injector` |
|:-------|:----------------------------------------|:----------------------------------------- |
| | `4.15 ms` (✅ **1.00x**) | `8.92 ms` (❌ *2.15x slower*) |

---
Made with [criterion-table](https://github.com/nu11ptr/criterion-table)

7 changes: 6 additions & 1 deletion src/gas_metering/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum GasMeter {
function: FunctionDefinition,
/// Instructions to be inlined before gas function invocation for better performance.
preamble: Vec<elements::Instruction>,
/// Instructions to be inlined after gas function invocation for better performance.
postamble: Vec<elements::Instruction>,
},
}

Expand Down Expand Up @@ -89,6 +91,7 @@ pub mod mutable_global {
let gas_func_sig = builder::SignatureBuilder::new()
.with_param(ValueType::I64)
.with_param(ValueType::I64)
.with_result(ValueType::I64)
.build_sig();
let gas_global_idx = module.globals_space() as u32;

Expand All @@ -100,7 +103,6 @@ pub mod mutable_global {
Instruction::GetLocal(0),
Instruction::GetLocal(1),
Instruction::I64Sub,
Instruction::SetGlobal(gas_global_idx),
Instruction::Return,
Instruction::End,
// sentinel val u64::MAX
Expand All @@ -117,10 +119,12 @@ pub mod mutable_global {
Instruction::I64Const(0), // gas func overhead cost, the value is actualized below
Instruction::I64Sub,
];
let postamble_instructions = vec![Instruction::SetGlobal(gas_global_idx)];
// calculate gas used for the gas charging func execution itself
let mut gas_fn_cost = func_instructions
.iter()
.chain(preamble_instructions.iter())
.chain(postamble_instructions.iter())
.fold(0, |cost, instruction| {
cost + (rules.instruction_cost(instruction).unwrap_or(0) as i64)
});
Expand Down Expand Up @@ -153,6 +157,7 @@ pub mod mutable_global {
global: self.global_name,
function: func,
preamble: preamble_instructions,
postamble: postamble_instructions,
}
}
}
Expand Down
35 changes: 28 additions & 7 deletions src/gas_metering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ pub fn inject<R: Rules, B: Backend>(

(import_count, functions_space + 1)
},
GasMeter::Internal { global, function: _, preamble: _ } => {
GasMeter::Internal { global, function: _, preamble: _, postamble: _ } => {
// Inject the gas counting global
mbuilder.push_global(
builder::global()
Expand Down Expand Up @@ -206,8 +206,11 @@ pub fn inject<R: Rules, B: Backend>(
let mut error = false;

let mut preamble = &vec![];
if let GasMeter::Internal { global: _, function: _, preamble: p } = &gas_func {
preamble = &*p;
let mut postamble = &vec![];
if let GasMeter::Internal { global: _, function: _, preamble: pre, postamble: post } = &gas_func
{
preamble = &*pre;
postamble = &*post;
};

// Iterate over module sections and perform needed transformations
Expand All @@ -225,7 +228,14 @@ pub fn inject<R: Rules, B: Backend>(
}
}
}
if inject_counter(func_body.code_mut(), &preamble, rules, gas_func_idx).is_err()
if inject_counter(
func_body.code_mut(),
&preamble,
&postamble,
rules,
gas_func_idx,
)
.is_err()
{
error = true;
break
Expand Down Expand Up @@ -289,7 +299,7 @@ pub fn inject<R: Rules, B: Backend>(
}

// Add local function if needed
if let GasMeter::Internal { global: _, function, preamble: _ } = gas_func {
if let GasMeter::Internal { global: _, function, preamble: _, postamble: _ } = gas_func {
module = add_local_func(module, function);
}

Expand Down Expand Up @@ -626,17 +636,25 @@ fn determine_metered_blocks<R: Rules>(
fn inject_counter<R: Rules>(
instructions: &mut elements::Instructions,
preamble_instructions: &Vec<elements::Instruction>,
postamble_instructions: &Vec<elements::Instruction>,
rules: &R,
gas_func: u32,
) -> Result<(), ()> {
let blocks = determine_metered_blocks(instructions, rules)?;
insert_metering_calls(instructions, preamble_instructions, blocks, gas_func)
insert_metering_calls(
instructions,
preamble_instructions,
postamble_instructions,
blocks,
gas_func,
)
}

// Then insert metering calls into a sequence of instructions given the block locations and costs.
fn insert_metering_calls(
instructions: &mut elements::Instructions,
preamble_instructions: &Vec<elements::Instruction>,
postamble_instructions: &Vec<elements::Instruction>,
blocks: Vec<MeteredBlock>,
gas_func: u32,
) -> Result<(), ()> {
Expand All @@ -656,9 +674,12 @@ fn insert_metering_calls(
if block.start_pos == original_pos {
for i in preamble_instructions {
new_instrs.push(i.clone());
}
} // instead, add it to the block.cost here VVV
new_instrs.push(I64Const(block.cost as i64));
new_instrs.push(Call(gas_func));
for i in postamble_instructions {
new_instrs.push(i.clone());
}
true
} else {
false
Expand Down

0 comments on commit e7b35c0

Please sign in to comment.