dfinity / canister-profiling

Collection of canister performance benchmarks
Apache License 2.0
21 stars 8 forks source link

bump `moc` to 0.8.8 #52

Closed ggreif closed 1 year ago

github-actions[bot] commented 1 year ago

Note Diffing the performance result against the published result from main branch. Unchanged benchmarks are omitted.

Map

binary_size generate 50k max mem batch_get 50 batch_put 50 batch_remove 50
hashmap 196_227 ($\textcolor{green}{-0.07\%}$) 2_387_017_574 9_102_052 1_293_015 ($\textcolor{green}{-0.03\%}$) 689_295_883 ($\textcolor{green}{-0.00\%}$) 1_224_704 ($\textcolor{green}{-0.03\%}$)
triemap 201_786 ($\textcolor{green}{-0.14\%}$) 2_286_509_386 ($\textcolor{green}{-0.13\%}$) 9_715_900 891_925 ($\textcolor{green}{-0.12\%}$) 2_111_535 ($\textcolor{green}{-0.18\%}$) 1_187_671 ($\textcolor{green}{-0.32\%}$)
rbtree 198_958 ($\textcolor{green}{-0.45\%}$) 2_024_735_614 ($\textcolor{green}{-0.52\%}$) 8_902_160 787_768 ($\textcolor{green}{-0.70\%}$) 1_839_147 ($\textcolor{green}{-0.63\%}$) 991_630 ($\textcolor{green}{-0.97\%}$)
splay 197_868 ($\textcolor{green}{-0.19\%}$) 2_305_505_782 ($\textcolor{green}{-0.27\%}$) 8_702_096 1_258_328 ($\textcolor{green}{-0.59\%}$) 2_175_053 ($\textcolor{green}{-0.34\%}$) 1_259_845 ($\textcolor{green}{-0.59\%}$)
btree 235_337 ($\textcolor{green}{-0.14\%}$) 2_122_255_521 ($\textcolor{green}{-0.19\%}$) 7_556_172 936_630 ($\textcolor{green}{-0.53\%}$) 1_954_939 ($\textcolor{green}{-0.26\%}$) 991_671 ($\textcolor{green}{-0.53\%}$)
zhenya_hashmap 190_491 ($\textcolor{green}{-0.04\%}$) 1_855_281_618 9_301_800 745_902 ($\textcolor{green}{-0.05\%}$) 1_651_310 ($\textcolor{green}{-0.02\%}$) 752_198 ($\textcolor{green}{-0.05\%}$)
btreemap_rs 514_775 ($\textcolor{green}{-0.25\%}$) 115_994_744 ($\textcolor{green}{-6.30\%}$) 1_638_400 59_433 ($\textcolor{green}{-0.48\%}$) 137_855 ($\textcolor{green}{-1.72\%}$) 61_795 ($\textcolor{green}{-0.47\%}$)
hashmap_rs 502_772 ($\textcolor{green}{-0.27\%}$) 53_333_947 ($\textcolor{red}{0.19\%}$) 1_835_008 21_070 ($\textcolor{green}{-1.36\%}$) 63_601 ($\textcolor{green}{-0.31\%}$) 22_484 ($\textcolor{green}{-1.29\%}$)

Priority queue

binary_size heapify 50k mem pop_min 50 put 50
heap 181_726 ($\textcolor{green}{-0.05\%}$) 793_253_862 ($\textcolor{green}{-0.02\%}$) 1_400_024 385_321 ($\textcolor{green}{-0.63\%}$) 822_756 ($\textcolor{green}{-0.18\%}$)
heap_rs 473_458 ($\textcolor{green}{-0.35\%}$) 5_041_433 ($\textcolor{green}{-0.00\%}$) 819_200 53_243 ($\textcolor{green}{-0.59\%}$) 22_092 ($\textcolor{green}{-0.85\%}$)

MoVM

binary_size generate 10k max mem batch_get 50 batch_put 50 batch_remove 50
hashmap 196_227 ($\textcolor{green}{-0.07\%}$) 477_464_161 1_820_844 1_291_042 ($\textcolor{green}{-0.03\%}$) 138_897_096 ($\textcolor{green}{-0.00\%}$) 1_222_118 ($\textcolor{green}{-0.03\%}$)
hashmap_rs 502_772 ($\textcolor{green}{-0.27\%}$) 10_984_247 ($\textcolor{red}{0.18\%}$) 950_272 20_385 ($\textcolor{green}{-1.41\%}$) 62_907 ($\textcolor{green}{-0.31\%}$) 21_374 ($\textcolor{green}{-1.36\%}$)
imrc_hashmap_rs 513_980 ($\textcolor{green}{-0.49\%}$) 19_919_391 ($\textcolor{red}{0.29\%}$) 1_572_864 31_519 ($\textcolor{green}{-0.95\%}$) 120_207 ($\textcolor{green}{-0.00\%}$) 37_618 ($\textcolor{green}{-0.79\%}$)
movm_rs 2_092_441 ($\textcolor{red}{2.89\%}$) 1_017_324_475 ($\textcolor{green}{-7.41\%}$) 2_654_208 2_494_635 ($\textcolor{green}{-9.09\%}$) 6_477_172 ($\textcolor{green}{-6.72\%}$) 5_106_080 ($\textcolor{green}{-5.74\%}$)
movm_dynamic_rs 2_295_206 ($\textcolor{red}{3.00\%}$) 496_274_407 ($\textcolor{green}{-10.67\%}$) 2_129_920 1_951_981 ($\textcolor{green}{-10.74\%}$) 2_709_572 ($\textcolor{green}{-9.99\%}$) 1_950_006 ($\textcolor{green}{-9.97\%}$)

Basic DAO

binary_size init transfer_token submit_proposal vote_proposal
Motoko 291_477 ($\textcolor{green}{-0.06\%}$) 44_445 ($\textcolor{green}{-0.02\%}$) 20_041 ($\textcolor{red}{0.59\%}$) 14_078 ($\textcolor{green}{-0.90\%}$) 16_680 ($\textcolor{green}{-0.78\%}$)
Rust 940_461 ($\textcolor{green}{-0.41\%}$) 541_441 ($\textcolor{green}{-0.13\%}$) 102_463 ($\textcolor{green}{-0.00\%}$) 125_485 ($\textcolor{green}{-0.16\%}$) 137_030 ($\textcolor{green}{-1.28\%}$)

DIP721 NFT

binary_size init mint_token transfer_token
Motoko 244_622 ($\textcolor{green}{-0.01\%}$) 13_379 24_678 5_358
Rust 1_005_637 ($\textcolor{red}{0.76\%}$) 144_162 ($\textcolor{green}{-2.03\%}$) 375_896 ($\textcolor{green}{-1.42\%}$) 94_757 ($\textcolor{green}{-0.79\%}$)

Heartbeat

binary_size heartbeat
Motoko 156_821 ($\textcolor{green}{-0.02\%}$) 5_324 ($\textcolor{green}{-40.70\%}$)
Rust 35_608 1_127

Timer

binary_size setTimer cancelTimer
Motoko 164_347 ($\textcolor{green}{-0.02\%}$) 19_476 1_907
Rust 524_361 ($\textcolor{green}{-0.25\%}$) 55_152 ($\textcolor{green}{-1.17\%}$) 10_417 ($\textcolor{green}{-1.18\%}$)

Garbage Collection

Note Same as main branch, skipping.

Actor class

binary size put new bucket put existing bucket get
Map 327_415 ($\textcolor{green}{-0.09\%}$) 812_472 ($\textcolor{green}{-0.19\%}$) 6_188 ($\textcolor{green}{-0.02\%}$) 6_532 ($\textcolor{green}{-0.02\%}$)

Publisher & Subscriber

pub_binary_size sub_binary_size subscribe_caller subscribe_callee publish_caller publish_callee
Motoko 181_458 ($\textcolor{green}{-0.02\%}$) 166_608 ($\textcolor{green}{-0.02\%}$) 16_644 ($\textcolor{green}{-0.01\%}$) 9_145 12_538 ($\textcolor{green}{-0.01\%}$) 4_001
Rust 561_379 ($\textcolor{green}{-0.46\%}$) 696_578 ($\textcolor{red}{0.06\%}$) 62_781 ($\textcolor{green}{-0.99\%}$) 42_457 ($\textcolor{green}{-1.70\%}$) 87_978 ($\textcolor{green}{-1.57\%}$) 49_653 ($\textcolor{green}{-1.76\%}$)
github-actions[bot] commented 1 year ago

Note The flamegraph link only works after you merge. Unchanged benchmarks are omitted.

Collection libraries

Measure different collection libraries written in both Motoko and Rust. The library names with _rs suffix are written in Rust; the rest are written in Motoko.

We use the same random number generator with fixed seed to ensure that all collections contain the same elements, and the queries are exactly the same. Below we explain the measurements of each column in the table:

💎 Takeaways

Note

  • The Candid interface of the benchmark is minimal, therefore the serialization cost is negligible in this measurement.
  • Due to the instrumentation overhead and cycle limit, we cannot profile computations with large collections. Hopefully, when deterministic time slicing is ready, we can measure the performance on larger memory footprint.
  • hashmap uses amortized data structure. When the initial capacity is reached, it has to copy the whole array, thus the cost of batch_put 50 is much higher than other data structures.
  • hashmap_rs uses the fxhash crate, which is the same as std::collections::HashMap, but with a deterministic hasher. This ensures reproducible result.
  • btree comes from Byron Becker's stable BTreeMap library.
  • zhenya_hashmap comes from Zhenya Usenko's stable HashMap library.
  • The MoVM table measures the performance of an experimental implementation of Motoko interpreter. External developers can ignore this table for now.

Map

binary_size generate 50k max mem batch_get 50 batch_put 50 batch_remove 50
hashmap 196_227 2_387_017_574 9_102_052 1_293_015 689_295_883 1_224_704
triemap 201_786 2_286_509_386 9_715_900 891_925 2_111_535 1_187_671
rbtree 198_958 2_024_735_614 8_902_160 787_768 1_839_147 991_630
splay 197_868 2_305_505_782 8_702_096 1_258_328 2_175_053 1_259_845
btree 235_337 2_122_255_521 7_556_172 936_630 1_954_939 991_671
zhenya_hashmap 190_491 1_855_281_618 9_301_800 745_902 1_651_310 752_198
btreemap_rs 514_775 115_994_744 1_638_400 59_433 137_855 61_795
hashmap_rs 502_772 53_333_947 1_835_008 21_070 63_601 22_484

Priority queue

binary_size heapify 50k mem pop_min 50 put 50
heap 181_726 793_253_862 1_400_024 385_321 822_756 386_887
heap_rs 473_458 5_041_433 819_200 53_243 22_092 53_420

MoVM

binary_size generate 10k max mem batch_get 50 batch_put 50 batch_remove 50
hashmap 196_227 477_464_161 1_820_844 1_291_042 138_897_096 1_222_118
hashmap_rs 502_772 10_984_247 950_272 20_385 62_907 21_374
imrc_hashmap_rs 513_980 19_919_391 1_572_864 31_519 120_207 37_618
movm_rs 2_092_441 1_017_324_475 2_654_208 2_494_635 6_477_172 5_106_080
movm_dynamic_rs 2_295_206 496_274_407 2_129_920 1_951_981 2_709_572 1_950_006

Sample Dapps

Measure the performance of some typical dapps:

Note

  • The cost difference is mainly due to the Candid serialization cost.
  • Motoko statically compiles/specializes the serialization code for each method, whereas in Rust, we use serde to dynamically deserialize data based on data on the wire.
  • We could improve the performance on the Rust side by using parser combinators. But it is a challenge to maintain the ergonomics provided by serde.
  • For real-world applications, we tend to send small data for each endpoint, which makes the Candid overhead in Rust tolerable.

Basic DAO

binary_size init transfer_token submit_proposal vote_proposal
Motoko 291_477 44_445 20_041 14_078 16_680
Rust 940_461 541_441 102_463 125_485 137_030

DIP721 NFT

binary_size init mint_token transfer_token
Motoko 244_622 13_379 24_678 5_358
Rust 1_005_637 144_162 375_896 94_757

Heartbeat / Timer

Measure the cost of empty heartbeat and timer job.

Heartbeat

binary_size heartbeat
Motoko 156_821 5_324
Rust 35_608 1_127

Timer

binary_size setTimer cancelTimer
Motoko 164_347 19_476 1_907
Rust 524_361 55_152 10_417

Motoko Specific Benchmarks

Measure various features only available in Motoko.

Garbage Collection

generate 80k max mem batch_get 50 batch_put 50 batch_remove 50
default 247_113_104 15_539_816 50 50 50
copying 247_113_054 15_539_816 247_107_545 247_259_605 247_259_929
compacting 409_359_701 15_539_816 308_335_627 348_771_032 352_659_043
generational 624_416_969 15_540_080 57_019 1_390_400 1_060_223

Actor class

binary size put new bucket put existing bucket get
Map 327_415 812_472 6_188 6_532

Publisher & Subscriber

Measure the cost of inter-canister calls from the Publisher & Subscriber example.

pub_binary_size sub_binary_size subscribe_caller subscribe_callee publish_caller publish_callee
Motoko 181_458 166_608 16_644 9_145 12_538 4_001
Rust 561_379 696_578 62_781 42_457 87_978 49_653