From 929e32bb3975dad8b44060d102a4f470eb42c2ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Wed, 18 Oct 2023 11:47:51 +0000 Subject: [PATCH 01/13] minimal benchmark setup --- scripts/cairo_bench.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/cairo_bench.sh b/scripts/cairo_bench.sh index a95e77a04d..74388b1d4b 100755 --- a/scripts/cairo_bench.sh +++ b/scripts/cairo_bench.sh @@ -5,7 +5,6 @@ if [ "$#" -lt 1 ]; then exit 1 fi -function run() { source scripts/cairo_test.sh -f bench_ | grep "DEBUG" | awk 'match($0, /0x[0-9a-fA-F]+/) { hex = substr($0, RSTART, RLENGTH); From c920e9c3a67a9fbd47ebfb2bf7fded1089bacf24 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Thu, 19 Oct 2023 08:44:14 +0000 Subject: [PATCH 02/13] simple struct benches --- benches.txt | 14 +++++++++++ crates/dojo-core/src/benchmarks.cairo | 34 +++++++++++++++++++++++++++ crates/dojo-core/src/world_test.cairo | 26 +++++++++++++++++--- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/benches.txt b/benches.txt index 99a8cec447..95e285eff1 100644 --- a/benches.txt +++ b/benches.txt @@ -1,4 +1,17 @@ bench empty: 0 + db del arr: 16010 + db get arr: 995548 +db get half arr: 545758 + dbi scan arr 1: 405824 + dbi scan arr 2: 746678 +dbi set arr 1st: 350334 +dbi set arr 2nd: 350334 + db set arr: 832428 + foo get macro: 974544 + foo init: 0 + foo serialize: 0 + foo set call: 817974 + foo values: 0 idx create 1st: 80050 idx dlt last: 112070 idx dlt !last: 112070 @@ -10,4 +23,5 @@ storage get: 16010 storage get mny: 268944 storage set: 16010 + storage set2: 16010 storage set mny: 263344 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 7619d1866c..fc76a20f96 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -7,6 +7,8 @@ use option::OptionTrait; use dojo::database; use dojo::database::{storage, index}; use dojo::packing::{shl, shr}; +use dojo::model::Model; +use dojo::world_test::Foo; const GAS_OFFSET: felt252 = 0x1_000000_000000_000000_000000_000000; // 15 bajtów @@ -187,3 +189,35 @@ fn bench_indexed_database_array() { assert(*(*values.at(0)).at(0) == 2, 'Wrong value at index 0!'); assert(*(*values.at(0)).at(1) == 4, 'Wrong value at index 1!'); } + + +#[test] +#[available_gas(1000000000)] +fn bench_simple_struct() { + let caller = starknet::contract_address_const::<0x42>(); + + let gas = start(); + let mut foo = Foo { + caller, + a: 0x123456789abcdef, + b: 0x123456789abcdef, + }; + end(gas, 'foo init'); + + let gas = start(); + let mut serialized = ArrayTrait::new(); + serde::Serde::serialize(@foo.caller, ref serialized); + serde::Serde::serialize(@foo.a, ref serialized); + serde::Serde::serialize(@foo.b, ref serialized); + let serialized = array::ArrayTrait::span(@serialized); + end(gas, 'foo serialize'); + + let gas = start(); + let values = foo.values(); + end(gas, 'foo values'); + + let gas = start(); + let keys = array!['database_test', '42'].span(); + storage::set(0, keys, 420); + end(gas, 'storage set2'); +} diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 69869c0d63..5b6f5b31ad 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -11,6 +11,7 @@ use dojo::executor::executor; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world}; use dojo::database::schema::SchemaIntrospection; use dojo::test_utils::{spawn_test_world, deploy_with_world_address}; +use dojo::benchmarks::{start, end}; #[derive(Model, Copy, Drop, Serde)] struct Foo { @@ -390,12 +391,31 @@ fn test_execute_multiple_worlds() { bar1_contract.set_foo(1337, 1337); bar2_contract.set_foo(7331, 7331); - let mut keys = ArrayTrait::new(); - keys.append(0); - let data1 = get!(world1, alice, Foo); let data2 = get!(world2, alice, Foo); assert(data1.a == 1337, 'data1 not stored'); assert(data2.a == 7331, 'data2 not stored'); } +#[test] +#[available_gas(60000000)] +fn bench_execute() { + let world = spawn_test_world(array![foo::TEST_CLASS_HASH],); + let bar_contract = IbarDispatcher { + contract_address: deploy_with_world_address(bar::TEST_CLASS_HASH, world) + }; + + let alice = starknet::contract_address_const::<0x1337>(); + starknet::testing::set_contract_address(alice); + + let gas = start(); + bar_contract.set_foo(1337, 1337); + end(gas, 'foo set call'); + + let gas = start(); + let data = get!(world, alice, Foo); + end(gas, 'foo get macro'); + + assert(data.a == 1337, 'data not stored'); +} + From a9df407181cf89afe3096151359b0902b63e226a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Thu, 19 Oct 2023 09:00:22 +0000 Subject: [PATCH 03/13] native storage benchmarks --- benches.txt | 6 ++++ crates/dojo-core/src/benchmarks.cairo | 43 +++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/benches.txt b/benches.txt index 95e285eff1..5bceade266 100644 --- a/benches.txt +++ b/benches.txt @@ -20,6 +20,12 @@ dbi set arr 2nd: 350334 idx query 2nd: 80050 idx query one: 80920 idx query two: 121380 + native prep: 4070 + native prep of: 4070 + native read: 5000 + native read of: 5000 + native write: 5000 + native writ of: 5000 storage get: 16010 storage get mny: 268944 storage set: 16010 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index fc76a20f96..b3f629595f 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -3,6 +3,8 @@ use array::ArrayTrait; use array::SpanTrait; use debug::PrintTrait; use option::OptionTrait; +use poseidon::poseidon_hash_span; +use starknet::SyscallResultTrait; use dojo::database; use dojo::database::{storage, index}; @@ -40,6 +42,7 @@ fn end(start: u128, name: felt252) { (used_gas + name).print(); } + #[test] #[available_gas(1000000000)] fn bench_reference_offset() { @@ -83,6 +86,46 @@ fn bench_storage_many() { assert(*res.at(1) == *values.at(1), 'value not set'); } +#[test] +#[available_gas(1000000000)] +fn bench_native_storage() { + let gas = start(); + let keys = array![0x1337].span(); + let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); + let address = starknet::storage_address_from_base(base); + end(gas, 'native prep'); + + let gas = start(); + starknet::storage_write_syscall(0, address, 42); + end(gas, 'native write'); + + let gas = start(); + let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); + end(gas, 'native read'); + + assert(value == 42, 'read invalid'); +} + +#[test] +#[available_gas(1000000000)] +fn bench_native_storage_offset() { + let gas = start(); + let keys = array![0x1337].span(); + let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); + let address = starknet::storage_address_from_base_and_offset(base, 42); + end(gas, 'native prep of'); + + let gas = start(); + starknet::storage_write_syscall(0, address, 42); + end(gas, 'native writ of'); + + let gas = start(); + let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); + end(gas, 'native read of'); + + assert(value == 42, 'read invalid'); +} + #[test] #[available_gas(1000000000)] fn bench_index() { From b93851142db6a020277ef94b2c271dd938c7029a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Thu, 19 Oct 2023 09:29:04 +0000 Subject: [PATCH 04/13] struct bench fix --- crates/dojo-core/src/benchmarks.cairo | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index b3f629595f..5e34c656a9 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -249,7 +249,6 @@ fn bench_simple_struct() { let gas = start(); let mut serialized = ArrayTrait::new(); - serde::Serde::serialize(@foo.caller, ref serialized); serde::Serde::serialize(@foo.a, ref serialized); serde::Serde::serialize(@foo.b, ref serialized); let serialized = array::ArrayTrait::span(@serialized); @@ -259,8 +258,8 @@ fn bench_simple_struct() { let values = foo.values(); end(gas, 'foo values'); - let gas = start(); - let keys = array!['database_test', '42'].span(); - storage::set(0, keys, 420); - end(gas, 'storage set2'); + assert(serialized.len() == 2, 'serialized wrong length'); + assert(values.len() == 2, 'value wrong length'); + assert(serialized.at(0) == values.at(0), 'serialized differ at 0'); + assert(serialized.at(1) == values.at(1), 'serialized differ at 1'); } From 91dfba04cf1df5b71f40ae2641e061ffe7a8f9c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Fri, 20 Oct 2023 17:53:55 +0000 Subject: [PATCH 05/13] benchmark anomaly fix and simple struct bench --- benches.txt | 63 ++++++++-------- crates/dojo-core/src/benchmarks.cairo | 100 ++++++++++++++++---------- 2 files changed, 94 insertions(+), 69 deletions(-) diff --git a/benches.txt b/benches.txt index 5bceade266..b39baa332f 100644 --- a/benches.txt +++ b/benches.txt @@ -1,33 +1,32 @@ bench empty: 0 - db del arr: 16010 - db get arr: 995548 -db get half arr: 545758 - dbi scan arr 1: 405824 - dbi scan arr 2: 746678 -dbi set arr 1st: 350334 -dbi set arr 2nd: 350334 - db set arr: 832428 - foo get macro: 974544 - foo init: 0 - foo serialize: 0 - foo set call: 817974 - foo values: 0 - idx create 1st: 80050 - idx dlt last: 112070 - idx dlt !last: 112070 - idx empty: 40460 - idx exists chk: 16010 - idx query 2nd: 80050 - idx query one: 80920 - idx query two: 121380 - native prep: 4070 - native prep of: 4070 - native read: 5000 - native read of: 5000 - native write: 5000 - native writ of: 5000 - storage get: 16010 -storage get mny: 268944 - storage set: 16010 - storage set2: 16010 -storage set mny: 263344 + db del arr: 14240 + db get arr: 1027288 +db get half arr: 726058 + dbi scan arr 1: 452874 + dbi scan arr 2: 805378 +dbi set arr 1st: 482814 +dbi set arr 2nd: 482634 + db set arr: 855808 + foo get macro: 972774 + foo init: 770 + foo serialize: 3620 + foo set call: 816204 + foo values: 13560 + idx create 1st: 78280 + idx dlt last: 284480 + idx dlt !last: 285040 + idx empty: 185890 + idx exists chk: 40520 + idx query 2nd: 187780 + idx query one: 119120 + idx query two: 159580 + native prep: 11600 + native prep of: 11600 + native read: 17880 + native read of: 17880 + native write: 17260 + native writ of: 17260 + storage get: 36860 +storage get mny: 297424 + storage set: 36600 +storage set mny: 284284 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 5e34c656a9..3006e6dca9 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -14,14 +14,10 @@ use dojo::world_test::Foo; const GAS_OFFSET: felt252 = 0x1_000000_000000_000000_000000_000000; // 15 bajtów -fn start() -> u128 { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - gas -} fn end(start: u128, name: felt252) { let gas_after = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let mut name: u256 = name.into(); // overwriting zeros with spaces @@ -38,7 +34,7 @@ fn end(start: u128, name: felt252) { }; let name: felt252 = (name % GAS_OFFSET.into()).try_into().unwrap(); - let used_gas = (start - gas_after).into() * GAS_OFFSET; + let used_gas = (start - gas_after - 1770).into() * GAS_OFFSET; (used_gas + name).print(); } @@ -46,7 +42,8 @@ fn end(start: u128, name: felt252) { #[test] #[available_gas(1000000000)] fn bench_reference_offset() { - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); end(gas, 'bench empty'); } @@ -55,11 +52,13 @@ fn bench_reference_offset() { fn bench_storage_single() { let keys = array!['database_test', '42'].span(); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); storage::set(0, keys, 420); end(gas, 'storage set'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let res = storage::get(0, keys); end(gas, 'storage get'); @@ -73,11 +72,13 @@ fn bench_storage_many() { let values = array![1, 2].span(); let layout = array![251, 251].span(); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); storage::set_many(0, keys, 0, values, layout); end(gas, 'storage set mny'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let res = storage::get_many(0, keys, 0, 2, layout); end(gas, 'storage get mny'); @@ -89,17 +90,20 @@ fn bench_storage_many() { #[test] #[available_gas(1000000000)] fn bench_native_storage() { - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let keys = array![0x1337].span(); let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); let address = starknet::storage_address_from_base(base); end(gas, 'native prep'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); starknet::storage_write_syscall(0, address, 42); end(gas, 'native write'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); end(gas, 'native read'); @@ -109,17 +113,20 @@ fn bench_native_storage() { #[test] #[available_gas(1000000000)] fn bench_native_storage_offset() { - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let keys = array![0x1337].span(); let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); let address = starknet::storage_address_from_base_and_offset(base, 42); end(gas, 'native prep of'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); starknet::storage_write_syscall(0, address, 42); end(gas, 'native writ of'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); end(gas, 'native read of'); @@ -129,42 +136,50 @@ fn bench_native_storage_offset() { #[test] #[available_gas(1000000000)] fn bench_index() { - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let no_query = index::query(0, 69, Option::None(())); end(gas, 'idx empty'); assert(no_query.len() == 0, 'entity indexed'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); index::create(0, 69, 420); end(gas, 'idx create 1st'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let query = index::query(0, 69, Option::None(())); end(gas, 'idx query one'); assert(query.len() == 1, 'entity not indexed'); assert(*query.at(0) == 420, 'entity value incorrect'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); index::create(0, 69, 1337); end(gas, 'idx query 2nd'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let two_query = index::query(0, 69, Option::None(())); end(gas, 'idx query two'); assert(two_query.len() == 2, 'index should have two query'); assert(*two_query.at(1) == 1337, 'entity value incorrect'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); index::exists(0, 69, 420); end(gas, 'idx exists chk'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); index::delete(0, 69, 420); end(gas, 'idx dlt !last'); assert(!index::exists(0, 69, 420), 'entity should not exist'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); index::delete(0, 69, 1337); end(gas, 'idx dlt last'); @@ -179,11 +194,13 @@ fn bench_database_array() { let half_layout = array![251, 251, 251, 251, 251].span(); let len = value.len(); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); database::set('table', 'key', 0, value, layout); end(gas, 'db set arr'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let res = database::get('table', 'key', 0, len, layout); end(gas, 'db get arr'); @@ -191,14 +208,16 @@ fn bench_database_array() { assert(*res.at(0) == *value.at(0), 'value not set'); assert(*res.at(1) == *value.at(1), 'value not set'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let second_res = database::get('table', 'key', 3, 8, array![251, 251, 251, 251, 251].span()); end(gas, 'db get half arr'); assert(second_res.len() == 5, 'wrong number of values'); assert(*second_res.at(0) == *value.at(3), 'value not set'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); database::del('table', 'key'); end(gas, 'db del arr'); } @@ -210,19 +229,23 @@ fn bench_indexed_database_array() { let odd = array![1, 3].span(); let layout = array![251, 251].span(); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); database::set_with_index('table', 'even', 0, even, layout); end(gas, 'dbi set arr 1st'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let (keys, values) = database::scan('table', Option::None(()), 2, layout); end(gas, 'dbi scan arr 1'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); database::set_with_index('table', 'odd', 0, odd, layout); end(gas, 'dbi set arr 2nd'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let (keys, values) = database::scan('table', Option::None(()), 2, layout); end(gas, 'dbi scan arr 2'); @@ -239,7 +262,8 @@ fn bench_indexed_database_array() { fn bench_simple_struct() { let caller = starknet::contract_address_const::<0x42>(); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let mut foo = Foo { caller, a: 0x123456789abcdef, @@ -247,15 +271,17 @@ fn bench_simple_struct() { }; end(gas, 'foo init'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@foo.a, ref serialized); serde::Serde::serialize(@foo.b, ref serialized); let serialized = array::ArrayTrait::span(@serialized); end(gas, 'foo serialize'); - let gas = start(); - let values = foo.values(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let values: Span = foo.values(); end(gas, 'foo values'); assert(serialized.len() == 2, 'serialized wrong length'); From 6896c6e6d0087524bae59d3c4331dd438a30eec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Fri, 20 Oct 2023 19:02:24 +0000 Subject: [PATCH 06/13] complex struct serialization benchmark --- benches.txt | 7 +- crates/dojo-core/src/benchmarks.cairo | 110 ++++++++++++++++++++++++++ crates/dojo-core/src/world_test.cairo | 13 ++- 3 files changed, 125 insertions(+), 5 deletions(-) diff --git a/benches.txt b/benches.txt index b39baa332f..17f4834314 100644 --- a/benches.txt +++ b/benches.txt @@ -1,4 +1,7 @@ bench empty: 0 + chars init: 860 +chars serialize: 32350 + chars values: 34840 db del arr: 14240 db get arr: 1027288 db get half arr: 726058 @@ -7,10 +10,10 @@ db get half arr: 726058 dbi set arr 1st: 482814 dbi set arr 2nd: 482634 db set arr: 855808 - foo get macro: 972774 + foo get macro: 1039434 foo init: 770 foo serialize: 3620 - foo set call: 816204 + foo set call: 835314 foo values: 13560 idx create 1st: 78280 idx dlt last: 284480 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 3006e6dca9..a01d7692e8 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -5,6 +5,7 @@ use debug::PrintTrait; use option::OptionTrait; use poseidon::poseidon_hash_span; use starknet::SyscallResultTrait; +use starknet::{contract_address_const, ContractAddress, ClassHash, get_caller_address}; use dojo::database; use dojo::database::{storage, index}; @@ -289,3 +290,112 @@ fn bench_simple_struct() { assert(serialized.at(0) == values.at(0), 'serialized differ at 0'); assert(serialized.at(1) == values.at(1), 'serialized differ at 1'); } + + +#[derive(Model, Copy, Drop, Serde)] +struct Character { + #[key] + caller: ContractAddress, + heigth: felt252, + abilities: Abilities, + stats: Stats, + weapon: Sword, + gold: u32, +} + +#[derive(Model, Copy, Drop, Serde)] +struct Abilities { + #[key] + strength: u8, + dexterity: u8, + constitution: u8, + intelligence: u8, + wisdom: u8, + charisma: u8, +} + +#[derive(Model, Copy, Drop, Serde)] +struct Stats { + #[key] + kills: u128, + deaths: u16, + rests: u32, + hits: u64, + blocks: u32, + walked: felt252, + runned: felt252, + finished: bool, + romances: u16, +} + +#[derive(Model, Copy, Drop, Serde)] +struct Sword { + #[key] + weigh: u16, + damage: u32, +} + + +#[test] +#[available_gas(1000000000)] +fn bench_complex_struct() { + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + + let char = Character { + caller: starknet::contract_address_const::<0x42>(), + heigth: 0x123456789abcdef, + abilities: Abilities { + strength: 0x12, + dexterity: 0x34, + constitution: 0x56, + intelligence: 0x78, + wisdom: 0x9a, + charisma: 0xbc, + }, + stats: Stats { + kills: 0x123456789abcdef, + deaths: 0x1234, + rests: 0x12345678, + hits: 0x123456789abcdef, + blocks: 0x12345678, + walked: 0x123456789abcdef, + runned: 0x123456789abcdef, + finished: true, + romances: 0x1234, + }, + weapon: Sword { + weigh: 0x1234, + damage: 0x12345678, + }, + gold: 0x12345678, + }; + end(gas, 'chars init'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let mut serialized = ArrayTrait::new(); + serde::Serde::serialize(@char.heigth, ref serialized); + serde::Serde::serialize(@char.abilities, ref serialized); + serde::Serde::serialize(@char.stats, ref serialized); + serde::Serde::serialize(@char.weapon, ref serialized); + serde::Serde::serialize(@char.gold, ref serialized); + let serialized = array::ArrayTrait::span(@serialized); + end(gas, 'chars serialize'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let values: Span = char.values(); + end(gas, 'chars values'); + + assert(serialized.len() == values.len(), 'serialized not equal'); + + let mut idx = 0; + loop { + if idx == serialized.len() { + break; + } + assert(serialized.at(idx) == values.at(idx), 'serialized differ'); + idx += 1; + }; +} \ No newline at end of file diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 5b6f5b31ad..1c4c6fe290 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -11,7 +11,7 @@ use dojo::executor::executor; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world}; use dojo::database::schema::SchemaIntrospection; use dojo::test_utils::{spawn_test_world, deploy_with_world_address}; -use dojo::benchmarks::{start, end}; +use dojo::benchmarks::end; #[derive(Model, Copy, Drop, Serde)] struct Foo { @@ -408,14 +408,21 @@ fn bench_execute() { let alice = starknet::contract_address_const::<0x1337>(); starknet::testing::set_contract_address(alice); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); bar_contract.set_foo(1337, 1337); end(gas, 'foo set call'); - let gas = start(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); let data = get!(world, alice, Foo); end(gas, 'foo get macro'); assert(data.a == 1337, 'data not stored'); } +#[test] +#[available_gas(60000000)] +fn bench_execute_complex() { + +} \ No newline at end of file From 8fbbddf1110c423038ce74fd74f80ea748e5edf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Fri, 20 Oct 2023 19:57:37 +0000 Subject: [PATCH 07/13] character struct without nesting --- benches.txt | 5 ++- crates/dojo-core/src/benchmarks.cairo | 58 +++++++++++++-------------- crates/dojo-core/src/world_test.cairo | 56 +++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 32 deletions(-) diff --git a/benches.txt b/benches.txt index 17f4834314..af75f50f46 100644 --- a/benches.txt +++ b/benches.txt @@ -1,7 +1,8 @@ bench empty: 0 + char set call: 840264 chars init: 860 -chars serialize: 32350 - chars values: 34840 +chars serialize: 3620 + chars values: 5940 db del arr: 14240 db get arr: 1027288 db get half arr: 726058 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index a01d7692e8..77dcbed735 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -297,9 +297,9 @@ struct Character { #[key] caller: ContractAddress, heigth: felt252, - abilities: Abilities, - stats: Stats, - weapon: Sword, + // abilities: Abilities, + // stats: Stats, + // weapon: Sword, gold: u32, } @@ -345,29 +345,29 @@ fn bench_complex_struct() { let char = Character { caller: starknet::contract_address_const::<0x42>(), heigth: 0x123456789abcdef, - abilities: Abilities { - strength: 0x12, - dexterity: 0x34, - constitution: 0x56, - intelligence: 0x78, - wisdom: 0x9a, - charisma: 0xbc, - }, - stats: Stats { - kills: 0x123456789abcdef, - deaths: 0x1234, - rests: 0x12345678, - hits: 0x123456789abcdef, - blocks: 0x12345678, - walked: 0x123456789abcdef, - runned: 0x123456789abcdef, - finished: true, - romances: 0x1234, - }, - weapon: Sword { - weigh: 0x1234, - damage: 0x12345678, - }, + // abilities: Abilities { + // strength: 0x12, + // dexterity: 0x34, + // constitution: 0x56, + // intelligence: 0x78, + // wisdom: 0x9a, + // charisma: 0xbc, + // }, + // stats: Stats { + // kills: 0x123456789abcdef, + // deaths: 0x1234, + // rests: 0x12345678, + // hits: 0x123456789abcdef, + // blocks: 0x12345678, + // walked: 0x123456789abcdef, + // runned: 0x123456789abcdef, + // finished: true, + // romances: 0x1234, + // }, + // weapon: Sword { + // weigh: 0x1234, + // damage: 0x12345678, + // }, gold: 0x12345678, }; end(gas, 'chars init'); @@ -376,9 +376,9 @@ fn bench_complex_struct() { gas::withdraw_gas().unwrap(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@char.heigth, ref serialized); - serde::Serde::serialize(@char.abilities, ref serialized); - serde::Serde::serialize(@char.stats, ref serialized); - serde::Serde::serialize(@char.weapon, ref serialized); + // serde::Serde::serialize(@char.abilities, ref serialized); + // serde::Serde::serialize(@char.stats, ref serialized); + // serde::Serde::serialize(@char.weapon, ref serialized); serde::Serde::serialize(@char.gold, ref serialized); let serialized = array::ArrayTrait::span(@serialized); end(gas, 'chars serialize'); diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 1c4c6fe290..9cbd9011b3 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -7,6 +7,7 @@ use starknet::class_hash::Felt252TryIntoClassHash; use starknet::{contract_address_const, ContractAddress, ClassHash, get_caller_address}; use starknet::syscalls::deploy_syscall; +use dojo::benchmarks::{Character, Abilities, Stats, Sword}; use dojo::executor::executor; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world}; use dojo::database::schema::SchemaIntrospection; @@ -31,11 +32,12 @@ struct Fizz { #[starknet::interface] trait Ibar { fn set_foo(self: @TContractState, a: felt252, b: u128); + fn set_char(self: @TContractState, a: felt252, b: u32); } #[starknet::contract] mod bar { - use super::{Foo, IWorldDispatcher, IWorldDispatcherTrait}; + use super::{Foo, IWorldDispatcher, IWorldDispatcherTrait, Character, Abilities, Stats, Sword}; use traits::Into; use starknet::{get_caller_address, ContractAddress}; @@ -53,6 +55,40 @@ mod bar { fn set_foo(self: @ContractState, a: felt252, b: u128) { set!(self.world.read(), Foo { caller: get_caller_address(), a, b }); } + + fn set_char(self: @ContractState, a: felt252, b: u32) { + set!( + self.world.read(), + Character { + caller: get_caller_address(), + heigth: a, + // abilities: Abilities { + // strength: 0x12, + // dexterity: 0x34, + // constitution: 0x56, + // intelligence: 0x78, + // wisdom: 0x9a, + // charisma: 0xbc, + // }, + // stats: Stats { + // kills: 0x123456789abcdef, + // deaths: 0x1234, + // rests: 0x12345678, + // hits: 0x123456789abcdef, + // blocks: 0x12345678, + // walked: 0x123456789abcdef, + // runned: 0x123456789abcdef, + // finished: true, + // romances: 0x1234, + // }, + // weapon: Sword { + // weigh: 0x1234, + // damage: 0x12345678, + // }, + gold: b, + } + ); + } } } @@ -424,5 +460,23 @@ fn bench_execute() { #[test] #[available_gas(60000000)] fn bench_execute_complex() { + let world = spawn_test_world(array![foo::TEST_CLASS_HASH],); + let bar_contract = IbarDispatcher { + contract_address: deploy_with_world_address(bar::TEST_CLASS_HASH, world) + }; + + let alice = starknet::contract_address_const::<0x1337>(); + starknet::testing::set_contract_address(alice); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + bar_contract.set_char(1337, 1337); + end(gas, 'char set call'); + + // let gas = testing::get_available_gas(); + // gas::withdraw_gas().unwrap(); + // let data = get!(world, alice, Foo); + // end(gas, 'foo get macro'); + // assert(data.a == 1337, 'data not stored'); } \ No newline at end of file From a9f127a5dfa53655e94095f5670fadce4c611e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Sat, 21 Oct 2023 11:34:34 +0000 Subject: [PATCH 08/13] nested struct test and issue --- crates/dojo-core/src/benchmarks.cairo | 144 +++++++++++++++++++------- crates/dojo-core/src/world_test.cairo | 48 +++++---- 2 files changed, 134 insertions(+), 58 deletions(-) diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 77dcbed735..a7dd8e0358 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -292,20 +292,78 @@ fn bench_simple_struct() { } +#[derive(Model, Copy, Drop, Serde)] +struct Sword { + #[key] + swordsmith: ContractAddress, + damage: u32, +} + +#[derive(Model, Copy, Drop, Serde)] +struct Case { + #[key] + owner: ContractAddress, + sword: Sword, +} + +#[test] +#[available_gas(1000000000)] +fn bench_nested_struct() { + let caller = starknet::contract_address_const::<0x42>(); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + + let mut case = Case { + owner: caller, + sword: Sword { + swordsmith: caller, + damage: 0x12345678, + }, + }; + end(gas, 'case init'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let mut serialized = ArrayTrait::new(); + serde::Serde::serialize(@case.sword.swordsmith, ref serialized); + serde::Serde::serialize(@case.sword.damage, ref serialized); + let serialized = array::ArrayTrait::span(@serialized); + end(gas, 'case serialize'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let values: Span = case.values(); + end(gas, 'case values'); + + assert(serialized.len() == values.len(), 'serialized not equal'); + let mut idx = 0; + loop { + if idx == serialized.len() { + break; + } + assert(serialized.at(idx) == values.at(idx), 'serialized differ'); + idx += 1; + }; + + assert(case.layout().len() == values.len(), 'layout inconsintent with values'); +} + + #[derive(Model, Copy, Drop, Serde)] struct Character { #[key] caller: ContractAddress, heigth: felt252, - // abilities: Abilities, - // stats: Stats, - // weapon: Sword, + abilities: Abilities, + stats: Stats, + weapon: Sword, gold: u32, } #[derive(Model, Copy, Drop, Serde)] struct Abilities { #[key] + caller: ContractAddress, strength: u8, dexterity: u8, constitution: u8, @@ -317,6 +375,7 @@ struct Abilities { #[derive(Model, Copy, Drop, Serde)] struct Stats { #[key] + caller: ContractAddress, kills: u128, deaths: u16, rests: u32, @@ -328,12 +387,6 @@ struct Stats { romances: u16, } -#[derive(Model, Copy, Drop, Serde)] -struct Sword { - #[key] - weigh: u16, - damage: u32, -} #[test] @@ -345,29 +398,31 @@ fn bench_complex_struct() { let char = Character { caller: starknet::contract_address_const::<0x42>(), heigth: 0x123456789abcdef, - // abilities: Abilities { - // strength: 0x12, - // dexterity: 0x34, - // constitution: 0x56, - // intelligence: 0x78, - // wisdom: 0x9a, - // charisma: 0xbc, - // }, - // stats: Stats { - // kills: 0x123456789abcdef, - // deaths: 0x1234, - // rests: 0x12345678, - // hits: 0x123456789abcdef, - // blocks: 0x12345678, - // walked: 0x123456789abcdef, - // runned: 0x123456789abcdef, - // finished: true, - // romances: 0x1234, - // }, - // weapon: Sword { - // weigh: 0x1234, - // damage: 0x12345678, - // }, + abilities: Abilities { + caller: starknet::contract_address_const::<0x42>(), + strength: 0x12, + dexterity: 0x34, + constitution: 0x56, + intelligence: 0x78, + wisdom: 0x9a, + charisma: 0xbc, + }, + stats: Stats { + caller: starknet::contract_address_const::<0x42>(), + kills: 0x123456789abcdef, + deaths: 0x1234, + rests: 0x12345678, + hits: 0x123456789abcdef, + blocks: 0x12345678, + walked: 0x123456789abcdef, + runned: 0x123456789abcdef, + finished: true, + romances: 0x1234, + }, + weapon: Sword { + swordsmith: starknet::contract_address_const::<0x69>(), + damage: 0x12345678, + }, gold: 0x12345678, }; end(gas, 'chars init'); @@ -376,9 +431,25 @@ fn bench_complex_struct() { gas::withdraw_gas().unwrap(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@char.heigth, ref serialized); - // serde::Serde::serialize(@char.abilities, ref serialized); - // serde::Serde::serialize(@char.stats, ref serialized); - // serde::Serde::serialize(@char.weapon, ref serialized); + serde::Serde::serialize(@char.abilities.caller, ref serialized); + serde::Serde::serialize(@char.abilities.strength, ref serialized); + serde::Serde::serialize(@char.abilities.dexterity, ref serialized); + serde::Serde::serialize(@char.abilities.constitution, ref serialized); + serde::Serde::serialize(@char.abilities.intelligence, ref serialized); + serde::Serde::serialize(@char.abilities.wisdom, ref serialized); + serde::Serde::serialize(@char.abilities.charisma, ref serialized); + serde::Serde::serialize(@char.stats.caller, ref serialized); + serde::Serde::serialize(@char.stats.kills, ref serialized); + serde::Serde::serialize(@char.stats.deaths, ref serialized); + serde::Serde::serialize(@char.stats.rests, ref serialized); + serde::Serde::serialize(@char.stats.hits, ref serialized); + serde::Serde::serialize(@char.stats.blocks, ref serialized); + serde::Serde::serialize(@char.stats.walked, ref serialized); + serde::Serde::serialize(@char.stats.runned, ref serialized); + serde::Serde::serialize(@char.stats.finished, ref serialized); + serde::Serde::serialize(@char.stats.romances, ref serialized); + serde::Serde::serialize(@char.weapon.swordsmith, ref serialized); + serde::Serde::serialize(@char.weapon.damage, ref serialized); serde::Serde::serialize(@char.gold, ref serialized); let serialized = array::ArrayTrait::span(@serialized); end(gas, 'chars serialize'); @@ -388,6 +459,9 @@ fn bench_complex_struct() { let values: Span = char.values(); end(gas, 'chars values'); + + serialized.len().print(); + values.len().print(); assert(serialized.len() == values.len(), 'serialized not equal'); let mut idx = 0; diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 9cbd9011b3..06dd0e9d83 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -62,29 +62,31 @@ mod bar { Character { caller: get_caller_address(), heigth: a, - // abilities: Abilities { - // strength: 0x12, - // dexterity: 0x34, - // constitution: 0x56, - // intelligence: 0x78, - // wisdom: 0x9a, - // charisma: 0xbc, - // }, - // stats: Stats { - // kills: 0x123456789abcdef, - // deaths: 0x1234, - // rests: 0x12345678, - // hits: 0x123456789abcdef, - // blocks: 0x12345678, - // walked: 0x123456789abcdef, - // runned: 0x123456789abcdef, - // finished: true, - // romances: 0x1234, - // }, - // weapon: Sword { - // weigh: 0x1234, - // damage: 0x12345678, - // }, + abilities: Abilities { + caller: get_caller_address(), + strength: 0x12, + dexterity: 0x34, + constitution: 0x56, + intelligence: 0x78, + wisdom: 0x9a, + charisma: 0xbc, + }, + stats: Stats { + caller: get_caller_address(), + kills: 0x123456789abcdef, + deaths: 0x1234, + rests: 0x12345678, + hits: 0x123456789abcdef, + blocks: 0x12345678, + walked: 0x123456789abcdef, + runned: 0x123456789abcdef, + finished: true, + romances: 0x1234, + }, + weapon: Sword { + swordsmith: get_caller_address(), + damage: 0x12345678, + }, gold: b, } ); From 3d00574f36715b5e5d129e48c4d25f2405a65a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Tue, 24 Oct 2023 12:51:56 +0000 Subject: [PATCH 09/13] passing character benchmark --- crates/dojo-core/src/benchmarks.cairo | 35 +++++---------------------- crates/dojo-core/src/world_test.cairo | 2 -- 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index a7dd8e0358..7f3196fee1 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -292,9 +292,8 @@ fn bench_simple_struct() { } -#[derive(Model, Copy, Drop, Serde)] +#[derive(Introspect, Copy, Drop, Serde)] struct Sword { - #[key] swordsmith: ContractAddress, damage: u32, } @@ -360,10 +359,8 @@ struct Character { gold: u32, } -#[derive(Model, Copy, Drop, Serde)] +#[derive(Introspect, Copy, Drop, Serde)] struct Abilities { - #[key] - caller: ContractAddress, strength: u8, dexterity: u8, constitution: u8, @@ -372,10 +369,8 @@ struct Abilities { charisma: u8, } -#[derive(Model, Copy, Drop, Serde)] +#[derive(Introspect, Copy, Drop, Serde)] struct Stats { - #[key] - caller: ContractAddress, kills: u128, deaths: u16, rests: u32, @@ -399,7 +394,6 @@ fn bench_complex_struct() { caller: starknet::contract_address_const::<0x42>(), heigth: 0x123456789abcdef, abilities: Abilities { - caller: starknet::contract_address_const::<0x42>(), strength: 0x12, dexterity: 0x34, constitution: 0x56, @@ -408,7 +402,6 @@ fn bench_complex_struct() { charisma: 0xbc, }, stats: Stats { - caller: starknet::contract_address_const::<0x42>(), kills: 0x123456789abcdef, deaths: 0x1234, rests: 0x12345678, @@ -431,25 +424,9 @@ fn bench_complex_struct() { gas::withdraw_gas().unwrap(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@char.heigth, ref serialized); - serde::Serde::serialize(@char.abilities.caller, ref serialized); - serde::Serde::serialize(@char.abilities.strength, ref serialized); - serde::Serde::serialize(@char.abilities.dexterity, ref serialized); - serde::Serde::serialize(@char.abilities.constitution, ref serialized); - serde::Serde::serialize(@char.abilities.intelligence, ref serialized); - serde::Serde::serialize(@char.abilities.wisdom, ref serialized); - serde::Serde::serialize(@char.abilities.charisma, ref serialized); - serde::Serde::serialize(@char.stats.caller, ref serialized); - serde::Serde::serialize(@char.stats.kills, ref serialized); - serde::Serde::serialize(@char.stats.deaths, ref serialized); - serde::Serde::serialize(@char.stats.rests, ref serialized); - serde::Serde::serialize(@char.stats.hits, ref serialized); - serde::Serde::serialize(@char.stats.blocks, ref serialized); - serde::Serde::serialize(@char.stats.walked, ref serialized); - serde::Serde::serialize(@char.stats.runned, ref serialized); - serde::Serde::serialize(@char.stats.finished, ref serialized); - serde::Serde::serialize(@char.stats.romances, ref serialized); - serde::Serde::serialize(@char.weapon.swordsmith, ref serialized); - serde::Serde::serialize(@char.weapon.damage, ref serialized); + serde::Serde::serialize(@char.abilities, ref serialized); + serde::Serde::serialize(@char.stats, ref serialized); + serde::Serde::serialize(@char.weapon, ref serialized); serde::Serde::serialize(@char.gold, ref serialized); let serialized = array::ArrayTrait::span(@serialized); end(gas, 'chars serialize'); diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 06dd0e9d83..e14763c998 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -63,7 +63,6 @@ mod bar { caller: get_caller_address(), heigth: a, abilities: Abilities { - caller: get_caller_address(), strength: 0x12, dexterity: 0x34, constitution: 0x56, @@ -72,7 +71,6 @@ mod bar { charisma: 0xbc, }, stats: Stats { - caller: get_caller_address(), kills: 0x123456789abcdef, deaths: 0x1234, rests: 0x12345678, From fd7365b4cb601372bcb7c5d05a8b04279b8367fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Tue, 24 Oct 2023 15:22:31 +0000 Subject: [PATCH 10/13] enum and tuple in characte --- benches.txt | 11 ++++++--- crates/dojo-core/src/benchmarks.cairo | 35 ++++++++++++++++++--------- crates/dojo-core/src/world_test.cairo | 19 ++++++++++----- scripts/cairo_bench.sh | 1 + 4 files changed, 45 insertions(+), 21 deletions(-) diff --git a/benches.txt b/benches.txt index af75f50f46..d726023949 100644 --- a/benches.txt +++ b/benches.txt @@ -1,8 +1,11 @@ bench empty: 0 - char set call: 840264 - chars init: 860 -chars serialize: 3620 - chars values: 5940 + case init: 770 + case serialize: 5810 + case values: 9720 + char set call: 6138134 + chars init: 1040 +chars serialize: 39120 + chars values: 41640 db del arr: 14240 db get arr: 1027288 db get half arr: 726058 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 7f3196fee1..91a92bf197 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -303,8 +303,10 @@ struct Case { #[key] owner: ContractAddress, sword: Sword, + material: felt252, } + #[test] #[available_gas(1000000000)] fn bench_nested_struct() { @@ -318,14 +320,18 @@ fn bench_nested_struct() { swordsmith: caller, damage: 0x12345678, }, + material: 'wooden', }; end(gas, 'case init'); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let gas = testing::get_available_gas(); gas::withdraw_gas().unwrap(); let mut serialized = ArrayTrait::new(); - serde::Serde::serialize(@case.sword.swordsmith, ref serialized); - serde::Serde::serialize(@case.sword.damage, ref serialized); + serde::Serde::serialize(@case.sword, ref serialized); + serde::Serde::serialize(@case.material, ref serialized); let serialized = array::ArrayTrait::span(@serialized); end(gas, 'case serialize'); @@ -355,7 +361,7 @@ struct Character { heigth: felt252, abilities: Abilities, stats: Stats, - weapon: Sword, + weapon: Weapon, gold: u32, } @@ -382,7 +388,11 @@ struct Stats { romances: u16, } - +#[derive(Introspect, Copy, Drop, Serde)] +enum Weapon { + DualWield: (Sword, Sword), + Fists: (Sword, Sword), // Introspect requires same arms +} #[test] #[available_gas(1000000000)] @@ -412,10 +422,16 @@ fn bench_complex_struct() { finished: true, romances: 0x1234, }, - weapon: Sword { - swordsmith: starknet::contract_address_const::<0x69>(), - damage: 0x12345678, - }, + weapon: Weapon::DualWield(( + Sword { + swordsmith: starknet::contract_address_const::<0x69>(), + damage: 0x12345678, + }, + Sword { + swordsmith: starknet::contract_address_const::<0x69>(), + damage: 0x12345678, + } + )), gold: 0x12345678, }; end(gas, 'chars init'); @@ -436,9 +452,6 @@ fn bench_complex_struct() { let values: Span = char.values(); end(gas, 'chars values'); - - serialized.len().print(); - values.len().print(); assert(serialized.len() == values.len(), 'serialized not equal'); let mut idx = 0; diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index e14763c998..156242a21e 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -7,7 +7,7 @@ use starknet::class_hash::Felt252TryIntoClassHash; use starknet::{contract_address_const, ContractAddress, ClassHash, get_caller_address}; use starknet::syscalls::deploy_syscall; -use dojo::benchmarks::{Character, Abilities, Stats, Sword}; +use dojo::benchmarks; use dojo::executor::executor; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world}; use dojo::database::schema::SchemaIntrospection; @@ -37,7 +37,8 @@ trait Ibar { #[starknet::contract] mod bar { - use super::{Foo, IWorldDispatcher, IWorldDispatcherTrait, Character, Abilities, Stats, Sword}; + use super::{Foo, IWorldDispatcher, IWorldDispatcherTrait}; + use super::benchmarks::{Character, Abilities, Stats, Weapon, Sword}; use traits::Into; use starknet::{get_caller_address, ContractAddress}; @@ -81,10 +82,16 @@ mod bar { finished: true, romances: 0x1234, }, - weapon: Sword { - swordsmith: get_caller_address(), - damage: 0x12345678, - }, + weapon: Weapon::DualWield(( + Sword { + swordsmith: get_caller_address(), + damage: 0x12345678, + }, + Sword { + swordsmith: get_caller_address(), + damage: 0x12345678, + } + )), gold: b, } ); diff --git a/scripts/cairo_bench.sh b/scripts/cairo_bench.sh index 74388b1d4b..a95e77a04d 100755 --- a/scripts/cairo_bench.sh +++ b/scripts/cairo_bench.sh @@ -5,6 +5,7 @@ if [ "$#" -lt 1 ]; then exit 1 fi +function run() { source scripts/cairo_test.sh -f bench_ | grep "DEBUG" | awk 'match($0, /0x[0-9a-fA-F]+/) { hex = substr($0, RSTART, RLENGTH); From 2fc9a8ccc081f965a03c9356fccf545b32773021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Tue, 24 Oct 2023 15:57:48 +0000 Subject: [PATCH 11/13] big index and db set benches --- benches.txt | 39 ---------------- crates/dojo-core/src/benchmarks.cairo | 65 ++++++++++++++++++++++++++- crates/dojo-core/src/world_test.cairo | 12 ++--- 3 files changed, 69 insertions(+), 47 deletions(-) diff --git a/benches.txt b/benches.txt index d726023949..e69de29bb2 100644 --- a/benches.txt +++ b/benches.txt @@ -1,39 +0,0 @@ - bench empty: 0 - case init: 770 - case serialize: 5810 - case values: 9720 - char set call: 6138134 - chars init: 1040 -chars serialize: 39120 - chars values: 41640 - db del arr: 14240 - db get arr: 1027288 -db get half arr: 726058 - dbi scan arr 1: 452874 - dbi scan arr 2: 805378 -dbi set arr 1st: 482814 -dbi set arr 2nd: 482634 - db set arr: 855808 - foo get macro: 1039434 - foo init: 770 - foo serialize: 3620 - foo set call: 835314 - foo values: 13560 - idx create 1st: 78280 - idx dlt last: 284480 - idx dlt !last: 285040 - idx empty: 185890 - idx exists chk: 40520 - idx query 2nd: 187780 - idx query one: 119120 - idx query two: 159580 - native prep: 11600 - native prep of: 11600 - native read: 17880 - native read of: 17880 - native write: 17260 - native writ of: 17260 - storage get: 36860 -storage get mny: 297424 - storage set: 36600 -storage set mny: 284284 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 91a92bf197..cd84fa106f 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -187,6 +187,49 @@ fn bench_index() { assert(!index::exists(0, 69, 1337), 'entity should not exist'); } +#[test] +#[available_gas(1000000000)] +fn bench_big_index() { + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let mut i = 0; + loop { + if i == 1000 { + break; + } + index::create(0, 69, i); + i += 1; + }; + end(gas, 'idx create 1000'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let query = index::query(0, 69, Option::None(())); + end(gas, 'idx query 1000'); + assert(query.len() == 1000, 'entity not indexed'); + assert(*query.at(420) == 420, 'entity value incorrect'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + index::exists(0, 69, 999); + end(gas, 'idx exists 1000'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + index::delete(0, 69, 999); + end(gas, 'idx dlt 1000'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + index::delete(0, 69, 420); + end(gas, 'idx dlt !1000 >'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + index::delete(0, 69, 420); + end(gas, 'idx dlt !1000 0'); +} + #[test] #[available_gas(1000000000)] fn bench_database_array() { @@ -350,9 +393,16 @@ fn bench_nested_struct() { idx += 1; }; - assert(case.layout().len() == values.len(), 'layout inconsintent with values'); -} + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::set('cases', '42', 0, case.values(), case.layout()); + end(gas, 'case db set'); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::get('cases', '42', 0, case.packed_size(), case.layout()); + end(gas, 'case db get'); +} #[derive(Model, Copy, Drop, Serde)] struct Character { @@ -462,4 +512,15 @@ fn bench_complex_struct() { assert(serialized.at(idx) == values.at(idx), 'serialized differ'); idx += 1; }; + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::set('chars', '42', 0, char.values(), char.layout()); + end(gas, 'chars db set'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::get('chars', '42', 0, char.packed_size(), char.layout()); + end(gas, 'chars db get'); + } \ No newline at end of file diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 156242a21e..36d260763b 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -12,7 +12,7 @@ use dojo::executor::executor; use dojo::world::{IWorldDispatcher, IWorldDispatcherTrait, world}; use dojo::database::schema::SchemaIntrospection; use dojo::test_utils::{spawn_test_world, deploy_with_world_address}; -use dojo::benchmarks::end; +use dojo::benchmarks::{Character, end}; #[derive(Model, Copy, Drop, Serde)] struct Foo { @@ -480,10 +480,10 @@ fn bench_execute_complex() { bar_contract.set_char(1337, 1337); end(gas, 'char set call'); - // let gas = testing::get_available_gas(); - // gas::withdraw_gas().unwrap(); - // let data = get!(world, alice, Foo); - // end(gas, 'foo get macro'); + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let data = get!(world, alice, Character); + end(gas, 'char get macro'); - // assert(data.a == 1337, 'data not stored'); + assert(data.heigth == 1337, 'data not stored'); } \ No newline at end of file From 9a5da421e03e8d76d589723f2ed6b49103d89e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Tue, 24 Oct 2023 16:11:18 +0000 Subject: [PATCH 12/13] assertion that file haven't changed --- benches.txt | 50 ++++++++++++++++++++++++++++++++++++++++++ scripts/cairo_bench.sh | 7 +++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/benches.txt b/benches.txt index e69de29bb2..184ff1ad62 100644 --- a/benches.txt +++ b/benches.txt @@ -0,0 +1,50 @@ + bench empty: 0 + case db get: 754572 + case db set: 338782 + case init: 770 + case serialize: 5810 + case values: 38520 + char get macro: 11091794 + chars db get: 10139064 + chars db set: 5050844 + char set call: 6139084 + chars init: 1040 +chars serialize: 39120 + chars values: 42270 + db del arr: 14240 + db get arr: 1027288 +db get half arr: 726058 + dbi scan arr 1: 452874 + dbi scan arr 2: 805378 +dbi set arr 1st: 482814 +dbi set arr 2nd: 482634 + db set arr: 855808 + foo get macro: 1039434 + foo init: 770 + foo serialize: 3620 + foo set call: 835314 + foo values: 13560 +idx create 1000: 189333070 + idx create 1st: 78280 +idx dlt !1000 0: 164350 + idx dlt 1000: 110300 +idx dlt !1000 >: 261360 + idx dlt last: 284480 + idx dlt !last: 285040 + idx empty: 185890 +idx exists 1000: 14240 + idx exists chk: 40520 + idx query 1000: 40716000 + idx query 2nd: 187780 + idx query one: 119120 + idx query two: 159580 + native prep: 11600 + native prep of: 11600 + native read: 17880 + native read of: 17880 + native write: 17260 + native writ of: 17260 + storage get: 36860 +storage get mny: 297424 + storage set: 36600 +storage set mny: 284284 diff --git a/scripts/cairo_bench.sh b/scripts/cairo_bench.sh index a95e77a04d..877a73a52a 100755 --- a/scripts/cairo_bench.sh +++ b/scripts/cairo_bench.sh @@ -1,7 +1,7 @@ #!/bin/bash if [ "$#" -lt 1 ]; then - echo "Usage: $0 [set|diff]" + echo "Usage: $0 [set|diff|assert]" exit 1 fi @@ -20,4 +20,9 @@ if [ $1 = "set" ]; then run | sort | tee benches.txt elif [ $1 = "diff" ]; then run | sort | diff benches.txt - +elif [ $1 = "assert" ]; then + run | sort | cmp benches.txt - +else + echo "Usage: $0 [set|diff|assert]" + exit 1 fi From e563e64d50f86eea4c022f6159d840823fc1b8e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Zaj=C4=85c?= Date: Tue, 24 Oct 2023 17:40:09 +0000 Subject: [PATCH 13/13] long struct bench --- benches.txt | 98 +++++++++++++++++++------- crates/dojo-core/src/benchmarks.cairo | 99 +++++++++++++++++++-------- crates/dojo-core/src/test_utils.cairo | 35 +++++++++- crates/dojo-erc/Scarb.lock | 20 ++++++ 4 files changed, 199 insertions(+), 53 deletions(-) create mode 100644 crates/dojo-erc/Scarb.lock diff --git a/benches.txt b/benches.txt index 184ff1ad62..b1273abbdc 100644 --- a/benches.txt +++ b/benches.txt @@ -1,50 +1,100 @@ bench empty: 0 - case db get: 754572 - case db set: 338782 + bench empty: 0 + case db get: 754172 + case db get: 754172 + case db set: 338382 + case db set: 338382 + case init: 770 case init: 770 - case serialize: 5810 - case values: 38520 - char get macro: 11091794 - chars db get: 10139064 - chars db set: 5050844 - char set call: 6139084 - chars init: 1040 -chars serialize: 39120 - chars values: 42270 + case serialize: 4610 + case serialize: 4610 + case values: 36120 + case values: 36120 + char get macro: 11009694 + char get macro: 11009694 + chars db get: 10136764 + chars db get: 10136764 + chars db set: 5028344 + chars db set: 5028344 + char set call: 6048284 + char set call: 6048284 + chars init: 770 + chars init: 770 +chars serialize: 18920 +chars serialize: 18920 + chars values: 22070 + chars values: 22070 db del arr: 14240 - db get arr: 1027288 -db get half arr: 726058 - dbi scan arr 1: 452874 - dbi scan arr 2: 805378 -dbi set arr 1st: 482814 -dbi set arr 2nd: 482634 - db set arr: 855808 - foo get macro: 1039434 + db del arr: 14240 + db get arr: 1026188 + db get arr: 1026188 +db get half arr: 725458 +db get half arr: 725458 + dbi scan arr 1: 452574 + dbi scan arr 1: 452574 + dbi scan arr 2: 804778 + dbi scan arr 2: 804778 +dbi set arr 1st: 482514 +dbi set arr 1st: 482514 +dbi set arr 2nd: 482334 +dbi set arr 2nd: 482334 + db set arr: 854708 + db set arr: 854708 + foo get macro: 1021934 + foo get macro: 1021934 + foo init: 770 foo init: 770 - foo serialize: 3620 - foo set call: 835314 - foo values: 13560 + foo serialize: 2220 + foo serialize: 2220 + foo set call: 813314 + foo set call: 813314 + foo values: 12160 + foo values: 12160 idx create 1000: 189333070 +idx create 1000: 189333070 + idx create 1st: 78280 idx create 1st: 78280 +idx dlt !1000 0: 164350 idx dlt !1000 0: 164350 idx dlt 1000: 110300 + idx dlt 1000: 110300 +idx dlt !1000 >: 261360 idx dlt !1000 >: 261360 idx dlt last: 284480 + idx dlt last: 284480 idx dlt !last: 285040 + idx dlt !last: 285040 + idx empty: 185890 idx empty: 185890 +idx exists 1000: 14240 idx exists 1000: 14240 idx exists chk: 40520 + idx exists chk: 40520 + idx query 1000: 40716000 idx query 1000: 40716000 idx query 2nd: 187780 + idx query 2nd: 187780 + idx query one: 119120 idx query one: 119120 idx query two: 159580 + idx query two: 159580 + native prep: 11600 native prep: 11600 + native prep of: 11600 native prep of: 11600 native read: 17880 + native read: 17880 + native read of: 17880 native read of: 17880 native write: 17260 + native write: 17260 native writ of: 17260 + native writ of: 17260 + storage get: 36860 storage get: 36860 -storage get mny: 297424 +storage get mny: 297124 +storage get mny: 297124 + storage set: 36600 storage set: 36600 -storage set mny: 284284 +storage set mny: 283984 +storage set mny: 283984 diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index cd84fa106f..62f21918ef 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -9,35 +9,9 @@ use starknet::{contract_address_const, ContractAddress, ClassHash, get_caller_ad use dojo::database; use dojo::database::{storage, index}; -use dojo::packing::{shl, shr}; use dojo::model::Model; use dojo::world_test::Foo; - -const GAS_OFFSET: felt252 = 0x1_000000_000000_000000_000000_000000; // 15 bajtów - - -fn end(start: u128, name: felt252) { - let gas_after = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - let mut name: u256 = name.into(); - - // overwriting zeros with spaces - let mut char = 0; - loop { - if char == 15 { - break; - } - // if given byte is zero - if shl(0xff, 8 * char) & name == 0 { - name = name | shl(0x20, 8 * char); // set space - } - char += 1; - }; - - let name: felt252 = (name % GAS_OFFSET.into()).try_into().unwrap(); - let used_gas = (start - gas_after - 1770).into() * GAS_OFFSET; - (used_gas + name).print(); -} +use dojo::test_utils::end; #[test] @@ -334,6 +308,76 @@ fn bench_simple_struct() { assert(serialized.at(1) == values.at(1), 'serialized differ at 1'); } +#[derive(Model, Copy, Drop, Serde)] +struct PositionWithQuaterions { + #[key] + id: felt252, + x: felt252, + y: felt252, + z: felt252, + a: felt252, + b: felt252, + c: felt252, + d: felt252, +} + +#[test] +#[available_gas(1000000000)] +fn test_struct_with_many_fields() { + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + + let mut pos = PositionWithQuaterions { + id: 0x123456789abcdef, + x: 0x123456789abcdef, + y: 0x123456789abcdef, + z: 0x123456789abcdef, + a: 0x123456789abcdef, + b: 0x123456789abcdef, + c: 0x123456789abcdef, + d: 0x123456789abcdef, + }; + end(gas, 'pos init'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let mut serialized = ArrayTrait::new(); + serde::Serde::serialize(@pos.x, ref serialized); + serde::Serde::serialize(@pos.y, ref serialized); + serde::Serde::serialize(@pos.z, ref serialized); + serde::Serde::serialize(@pos.a, ref serialized); + serde::Serde::serialize(@pos.b, ref serialized); + serde::Serde::serialize(@pos.c, ref serialized); + serde::Serde::serialize(@pos.d, ref serialized); + let serialized = array::ArrayTrait::span(@serialized); + end(gas, 'pos serialize'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let values: Span = pos.values(); + end(gas, 'pos values'); + + assert(serialized.len() == values.len(), 'serialized not equal'); + let mut idx = 0; + loop { + if idx == serialized.len() { + break; + } + assert(serialized.at(idx) == values.at(idx), 'serialized differ'); + idx += 1; + }; + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::set('positions', '42', 0, pos.values(), pos.layout()); + end(gas, 'pos db set'); + + let gas = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + database::get('positions', '42', 0, pos.packed_size(), pos.layout()); + end(gas, 'pos db get'); +} + #[derive(Introspect, Copy, Drop, Serde)] struct Sword { @@ -522,5 +566,4 @@ fn bench_complex_struct() { gas::withdraw_gas().unwrap(); database::get('chars', '42', 0, char.packed_size(), char.layout()); end(gas, 'chars db get'); - } \ No newline at end of file diff --git a/crates/dojo-core/src/test_utils.cairo b/crates/dojo-core/src/test_utils.cairo index 5d10875ec9..8cc2bec88d 100644 --- a/crates/dojo-core/src/test_utils.cairo +++ b/crates/dojo-core/src/test_utils.cairo @@ -6,10 +6,11 @@ use array::{ArrayTrait, SpanTrait}; use traits::TryInto; use option::OptionTrait; use core::{result::ResultTrait, traits::Into}; - +use debug::PrintTrait; use dojo::executor::executor; use dojo::world::{world, IWorldDispatcher, IWorldDispatcherTrait}; +use dojo::packing::{shl, shr}; /// Deploy classhash with calldata for constructor /// @@ -68,3 +69,35 @@ fn spawn_test_world(models: Array) -> IWorldDispatcher { world } + + +const GAS_OFFSET: felt252 = 0x1_000000_000000_000000_000000_000000; // 15 bajtów + +/// Measures gas used after previous measurement and prints it +/// +/// # Arguments +/// +/// * `start` - gas before measurement +/// * `name` - name of test, at most 15 bytes, will be padded with spaces +fn end(start: u128, name: felt252) { + let gas_after = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + let mut name: u256 = name.into(); + + // overwriting zeros with spaces + let mut char = 0; + loop { + if char == 15 { + break; + } + // if given byte is zero + if shl(0xff, 8 * char) & name == 0 { + name = name | shl(0x20, 8 * char); // set space + } + char += 1; + }; + + let name: felt252 = (name % GAS_OFFSET.into()).try_into().unwrap(); + let used_gas = (start - gas_after - 1770).into() * GAS_OFFSET; + (used_gas + name).print(); +} diff --git a/crates/dojo-erc/Scarb.lock b/crates/dojo-erc/Scarb.lock new file mode 100644 index 0000000000..b00f21f531 --- /dev/null +++ b/crates/dojo-erc/Scarb.lock @@ -0,0 +1,20 @@ +# Code generated by scarb DO NOT EDIT. +version = 1 + +[[package]] +name = "dojo" +version = "0.3.1" +dependencies = [ + "dojo_plugin", +] + +[[package]] +name = "dojo_erc" +version = "0.3.1" +dependencies = [ + "dojo", +] + +[[package]] +name = "dojo_plugin" +version = "0.3.1"