dfinity / canister-profiling

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

bump moc and cdk #103

Closed chenyan-dfinity closed 9 months ago

github-actions[bot] commented 9 months ago

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

Map

binary_size generate 1m max mem batch_get 50 batch_put 50 batch_remove 50 upgrade
hashmap 188_910 ($\textcolor{red}{17.77\%}$) 8_370_838_990 ($\textcolor{green}{-2.10\%}$) 61_987_852 344_911 ($\textcolor{green}{-1.40\%}$) 6_593_215_386 ($\textcolor{green}{-0.72\%}$) 371_223 ($\textcolor{green}{-1.74\%}$) 11_026_881_645 ($\textcolor{green}{-2.19\%}$)
triemap 194_820 ($\textcolor{red}{19.08\%}$) 13_855_040_241 ($\textcolor{green}{-9.26\%}$) 74_216_172 254_589 ($\textcolor{green}{-15.53\%}$) 661_468 ($\textcolor{green}{-10.31\%}$) 650_780 ($\textcolor{green}{-9.94\%}$) 15_817_667_776 ($\textcolor{green}{-8.58\%}$)
rbtree 185_823 ($\textcolor{red}{17.44\%}$) 7_127_314_751 ($\textcolor{green}{-7.03\%}$) 57_996_060 114_300 ($\textcolor{green}{-1.16\%}$) 318_392 ($\textcolor{green}{-8.05\%}$) 328_237 ($\textcolor{green}{-11.51\%}$) 7_169_324_321 ($\textcolor{green}{-0.86\%}$)
splay 189_838 ($\textcolor{red}{18.61\%}$) 13_247_301_683 ($\textcolor{green}{-13.92\%}$) 53_995_996 628_581 ($\textcolor{green}{-14.89\%}$) 661_619 ($\textcolor{green}{-14.94\%}$) 921_933 ($\textcolor{green}{-14.44\%}$) 4_567_871_409 ($\textcolor{green}{-5.47\%}$)
btree 229_184 ($\textcolor{red}{21.90\%}$) 10_266_012_845 ($\textcolor{green}{-7.02\%}$) 31_104_012 353_622 ($\textcolor{green}{-6.00\%}$) 482_125 ($\textcolor{green}{-7.19\%}$) 533_935 ($\textcolor{green}{-7.50\%}$) 3_134_166_577 ($\textcolor{green}{-0.91\%}$)
zhenya_hashmap 188_597 ($\textcolor{red}{17.30\%}$) 2_570_553_414 ($\textcolor{green}{-9.44\%}$) 22_773_100 60_196 ($\textcolor{green}{-9.28\%}$) 70_137 ($\textcolor{green}{-16.79\%}$) 82_453 ($\textcolor{green}{-14.66\%}$) 3_305_570_068 ($\textcolor{green}{-1.43\%}$)
btreemap_rs 471_597 ($\textcolor{green}{-1.47\%}$) 1_797_168_136 ($\textcolor{green}{-0.00\%}$) 27_525_120 ($\textcolor{green}{-0.24\%}$) 75_572 ($\textcolor{green}{-0.00\%}$) 125_436 ($\textcolor{green}{-0.00\%}$) 86_322 ($\textcolor{green}{-0.00\%}$) 2_941_064_929 ($\textcolor{green}{-0.00\%}$)
imrc_hashmap_rs 477_125 ($\textcolor{green}{-1.17\%}$) 2_584_652_896 ($\textcolor{green}{-0.00\%}$) 244_973_568 38_416 ($\textcolor{green}{-0.06\%}$) 179_265 ($\textcolor{green}{-0.01\%}$) 115_565 ($\textcolor{green}{-0.02\%}$) 5_796_576_120 ($\textcolor{green}{-0.00\%}$)
hashmap_rs 464_990 ($\textcolor{green}{-0.87\%}$) 433_765_792 ($\textcolor{green}{-0.00\%}$) 73_072_640 ($\textcolor{green}{-0.09\%}$) 21_855 ($\textcolor{green}{-0.00\%}$) 26_957 ($\textcolor{green}{-0.00\%}$) 25_222 ($\textcolor{green}{-0.00\%}$) 1_293_478_901 ($\textcolor{green}{-0.00\%}$)

Priority queue

binary_size heapify 1m max mem pop_min 50 put 50 pop_min 50.1 upgrade
heap 166_808 ($\textcolor{red}{12.78\%}$) 5_697_879_935 ($\textcolor{green}{-10.88\%}$) 29_995_956 621_338 ($\textcolor{green}{-11.47\%}$) 228_674 ($\textcolor{green}{-11.65\%}$) 592_198 ($\textcolor{green}{-11.44\%}$) 3_309_814_038 ($\textcolor{green}{-0.84\%}$)
heap_rs 459_314 ($\textcolor{green}{-0.76\%}$) 138_669_874 ($\textcolor{green}{-0.00\%}$) 18_219_008 ($\textcolor{green}{-0.36\%}$) 57_563 ($\textcolor{green}{-0.00\%}$) 23_345 ($\textcolor{green}{-0.00\%}$) 57_695 ($\textcolor{green}{-0.00\%}$) 511_961_183 ($\textcolor{green}{-0.00\%}$)

Growable array

binary_size generate 5k max mem batch_get 500 batch_put 500 batch_remove 500 upgrade
buffer 173_215 ($\textcolor{red}{14.54\%}$) 2_570_947 ($\textcolor{green}{-8.56\%}$) 65_644 95_490 ($\textcolor{green}{-12.82\%}$) 800_452 ($\textcolor{green}{-9.55\%}$) 170_490 ($\textcolor{green}{-4.23\%}$) 3_061_307 ($\textcolor{green}{-4.53\%}$)
vector 171_563 ($\textcolor{red}{12.25\%}$) 1_920_997 ($\textcolor{green}{-13.81\%}$) 24_580 126_114 ($\textcolor{green}{-13.72\%}$) 183_385 ($\textcolor{green}{-13.66\%}$) 175_981 ($\textcolor{green}{-13.71\%}$) 4_695_522 ($\textcolor{green}{-2.38\%}$)
vec_rs 453_413 ($\textcolor{green}{-1.56\%}$) 289_090 ($\textcolor{green}{-0.00\%}$) 1_310_720 17_298 ($\textcolor{green}{-0.01\%}$) 30_623 25_758 ($\textcolor{green}{-0.00\%}$) 3_171_665 ($\textcolor{green}{-0.01\%}$)

Stable structures

binary_size generate 50k max mem batch_get 50 batch_put 50 batch_remove 50 upgrade
btreemap_rs 471_597 ($\textcolor{green}{-1.47\%}$) 76_392_040 ($\textcolor{green}{-0.00\%}$) 2_490_368 ($\textcolor{green}{-2.56\%}$) 65_130 ($\textcolor{green}{-0.00\%}$) 97_326 ($\textcolor{green}{-0.00\%}$) 85_331 ($\textcolor{green}{-0.00\%}$) 126_467_332 ($\textcolor{green}{-0.00\%}$)
btreemap_stable_rs 483_530 ($\textcolor{green}{-1.05\%}$) 5_255_631_698 ($\textcolor{green}{-0.00\%}$) 2_031_616 3_167_240 ($\textcolor{green}{-0.00\%}$) 5_784_534 ($\textcolor{green}{-0.00\%}$) 9_888_430 ($\textcolor{red}{0.00\%}$) 731_136 ($\textcolor{red}{0.00\%}$)
heap_rs 459_314 ($\textcolor{green}{-0.76\%}$) 7_001_770 ($\textcolor{green}{-0.00\%}$) 2_228_224 ($\textcolor{green}{-2.86\%}$) 50_072 ($\textcolor{green}{-0.00\%}$) 23_593 ($\textcolor{green}{-0.00\%}$) 50_044 ($\textcolor{green}{-0.00\%}$) 26_819_689 ($\textcolor{green}{-0.00\%}$)
heap_stable_rs 444_563 ($\textcolor{green}{-1.37\%}$) 319_633_532 ($\textcolor{red}{0.00\%}$) 458_752 2_674_735 ($\textcolor{green}{-0.00\%}$) 278_363 ($\textcolor{green}{-0.00\%}$) 2_654_537 ($\textcolor{green}{-0.00\%}$) 731_285 ($\textcolor{red}{0.00\%}$)
vec_rs 453_413 ($\textcolor{green}{-1.56\%}$) 3_079_434 ($\textcolor{green}{-0.00\%}$) 2_228_224 17_298 ($\textcolor{green}{-0.01\%}$) 18_473 17_999 ($\textcolor{green}{-0.01\%}$) 24_772_181 ($\textcolor{green}{-0.00\%}$)
vec_stable_rs 441_204 ($\textcolor{green}{-1.67\%}$) 75_145_327 ($\textcolor{green}{-0.00\%}$) 458_752 71_671 ($\textcolor{red}{1.91\%}$) 91_519 ($\textcolor{green}{-0.00\%}$) 94_915 ($\textcolor{red}{1.28\%}$) 731_270 ($\textcolor{green}{-0.00\%}$)

Statistics

SHA-2

binary_size SHA-256 SHA-512 account_id neuron_id
Motoko 195_805 ($\textcolor{red}{12.91\%}$) 273_037_084 ($\textcolor{green}{-8.29\%}$) 259_835_224 ($\textcolor{green}{-7.77\%}$) 34_373 ($\textcolor{green}{-8.91\%}$) 24_897 ($\textcolor{green}{-8.35\%}$)
Rust 476_042 ($\textcolor{green}{-0.59\%}$) 82_788_038 ($\textcolor{green}{-0.00\%}$) 56_793_082 ($\textcolor{green}{-0.00\%}$) 48_636 ($\textcolor{green}{-1.66\%}$) 51_163 ($\textcolor{green}{-1.84\%}$)

Certified map

binary_size generate 10k max mem inc witness upgrade
Motoko 244_500 ($\textcolor{red}{18.31\%}$) 4_763_348_103 ($\textcolor{green}{-9.36\%}$) 3_430_044 565_117 ($\textcolor{green}{-9.39\%}$) 402_073 ($\textcolor{green}{-7.85\%}$) 274_275_937 ($\textcolor{green}{-0.12\%}$)
Rust 498_197 ($\textcolor{green}{-1.06\%}$) 6_309_529_789 ($\textcolor{green}{-0.00\%}$) 2_228_224 1_004_188 ($\textcolor{green}{-0.00\%}$) 301_339 ($\textcolor{green}{-0.04\%}$) 5_926_705_684 ($\textcolor{green}{-0.00\%}$)

Statistics

Basic DAO

binary_size init transfer_token submit_proposal vote_proposal upgrade
Motoko 274_773 ($\textcolor{red}{15.78\%}$) 510_733 ($\textcolor{green}{-0.09\%}$) 22_316 ($\textcolor{green}{-2.30\%}$) 18_548 ($\textcolor{green}{-2.77\%}$) 19_597 ($\textcolor{green}{-3.09\%}$) 157_638 ($\textcolor{green}{-0.11\%}$)
Rust 778_222 ($\textcolor{green}{-0.55\%}$) 611_282 ($\textcolor{green}{-0.42\%}$) 101_374 ($\textcolor{green}{-0.54\%}$) 125_148 ($\textcolor{green}{-0.71\%}$) 137_434 ($\textcolor{green}{-0.28\%}$) 1_816_495 ($\textcolor{green}{-0.47\%}$)

DIP721 NFT

binary_size init mint_token transfer_token upgrade
Motoko 221_922 ($\textcolor{red}{13.44\%}$) 481_158 ($\textcolor{red}{0.01\%}$) 29_810 ($\textcolor{green}{-0.20\%}$) 8_776 ($\textcolor{green}{-1.35\%}$) 89_459 ($\textcolor{green}{-0.59\%}$)
Rust 790_671 ($\textcolor{green}{-1.68\%}$) 239_293 ($\textcolor{green}{-0.62\%}$) 368_586 ($\textcolor{green}{-0.30\%}$) 89_013 ($\textcolor{green}{-3.16\%}$) 2_001_978 ($\textcolor{green}{-0.61\%}$)

Statistics

Heartbeat

binary_size heartbeat
Motoko 137_205 ($\textcolor{red}{10.75\%}$) 23_182 ($\textcolor{green}{-0.55\%}$)
Rust 23_873 ($\textcolor{red}{0.13\%}$) 1_172

Timer

binary_size setTimer cancelTimer
Motoko 145_582 ($\textcolor{red}{11.85\%}$) 51_467 ($\textcolor{green}{-1.36\%}$) 4_610 ($\textcolor{green}{-0.92\%}$)
Rust 420_710 ($\textcolor{green}{-0.66\%}$) 68_153 ($\textcolor{green}{-0.08\%}$) 11_161 ($\textcolor{green}{-0.05\%}$)

Statistics

Garbage Collection

generate 700k max mem batch_get 50 batch_put 50 batch_remove 50
default 1_171_395_786 ($\textcolor{red}{0.00\%}$) 51_991_392 119 119 119
copying 1_171_395_668 ($\textcolor{red}{0.00\%}$) 51_991_392 1_171_104_136 ($\textcolor{green}{-0.00\%}$) 1_171_195_696 ($\textcolor{green}{-0.00\%}$) 1_171_106_949 ($\textcolor{green}{-0.00\%}$)
compacting 1_672_114_659 ($\textcolor{green}{-0.00\%}$) 51_991_392 1_290_052_154 ($\textcolor{green}{-0.00\%}$) 1_533_417_828 ($\textcolor{green}{-0.00\%}$) 1_564_512_242 ($\textcolor{green}{-0.00\%}$)
generational 2_529_073_372 ($\textcolor{green}{-0.00\%}$) 51_999_856 999_515_201 ($\textcolor{green}{-0.00\%}$) 1_232_740 ($\textcolor{red}{0.04\%}$) 1_103_853 ($\textcolor{red}{0.04\%}$)
incremental 29_503_138 ($\textcolor{red}{0.00\%}$) 985_890_580 ($\textcolor{red}{0.00\%}$) 333_755_986 ($\textcolor{green}{-0.00\%}$) 336_886_802 336_875_628

Actor class

binary size put new bucket put existing bucket get
Map 299_052 ($\textcolor{red}{14.17\%}$) 813_512 ($\textcolor{red}{13.66\%}$) 16_099 ($\textcolor{green}{-1.21\%}$) 16_644 ($\textcolor{green}{-0.95\%}$)

Statistics

Publisher & Subscriber

pub_binary_size sub_binary_size subscribe_caller subscribe_callee publish_caller publish_callee
Motoko 161_257 ($\textcolor{red}{11.19\%}$) 145_541 ($\textcolor{red}{10.38\%}$) 28_593 ($\textcolor{green}{-0.67\%}$) 11_963 ($\textcolor{green}{-0.11\%}$) 22_864 ($\textcolor{green}{-1.01\%}$) 6_430 ($\textcolor{green}{-0.14\%}$)
Rust 456_613 ($\textcolor{green}{-0.37\%}$) 507_753 ($\textcolor{green}{-0.79\%}$) 69_189 ($\textcolor{green}{-0.95\%}$) 42_865 ($\textcolor{red}{0.01\%}$) 92_768 ($\textcolor{green}{-0.13\%}$) 52_116 ($\textcolor{red}{0.01\%}$)

Statistics

github-actions[bot] commented 9 months 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. The _stable and _stable_rs suffix represents that the library directly writes the state to stable memory using Region in Motoko and ic-stable-stuctures in Rust.

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 very large collections.
  • The upgrade column uses Candid for serializing stable data. In Rust, you may get better cycle cost by using a different serialization format. Another slowdown in Rust is that ic-stable-structures tends to be slower than the region memory in Motoko.
  • Different library has different ways for persisting data during upgrades, there are mainly three categories:
    • Use stable variable directly in Motoko: zhenya_hashmap, btree, vector
    • Expose and serialize external state (share/unshare in Motoko, candid::Encode in Rust): rbtree, heap, btreemap_rs, hashmap_rs, heap_rs, vector_rs
    • Use pre/post-upgrade hooks to convert data into an array: hashmap, splay, triemap, buffer, imrc_hashmap_rs
  • The stable benchmarks are much more expensive than their non-stable counterpart, because the stable memory API is much more expensive. The benefit is that they get fast upgrade. The upgrade still needs to parse the metadata when initializing the upgraded Wasm module.
  • 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.
  • btree comes from mops.one/stableheapbtreemap.
  • zhenya_hashmap comes from mops.one/map.
  • vector comes from mops.one/vector. Compare with buffer, put has better worst case time and space complexity ($O(\sqrt{n})$ vs $O(n)$); get has a slightly larger constant overhead.
  • hashmap_rs uses the fxhash crate, which is the same as std::collections::HashMap, but with a deterministic hasher. This ensures reproducible result.
  • imrc_hashmap_rs uses the im-rc crate, which is the immutable version hashmap in Rust.

Map

binary_size generate 1m max mem batch_get 50 batch_put 50 batch_remove 50 upgrade
hashmap 188_910 8_370_838_990 61_987_852 344_911 6_593_215_386 371_223 11_026_881_645
triemap 194_820 13_855_040_241 74_216_172 254_589 661_468 650_780 15_817_667_776
rbtree 185_823 7_127_314_751 57_996_060 114_300 318_392 328_237 7_169_324_321
splay 189_838 13_247_301_683 53_995_996 628_581 661_619 921_933 4_567_871_409
btree 229_184 10_266_012_845 31_104_012 353_622 482_125 533_935 3_134_166_577
zhenya_hashmap 188_597 2_570_553_414 22_773_100 60_196 70_137 82_453 3_305_570_068
btreemap_rs 471_597 1_797_168_136 27_525_120 75_572 125_436 86_322 2_941_064_929
imrc_hashmap_rs 477_125 2_584_652_896 244_973_568 38_416 179_265 115_565 5_796_576_120
hashmap_rs 464_990 433_765_792 73_072_640 21_855 26_957 25_222 1_293_478_901

Priority queue

binary_size heapify 1m max mem pop_min 50 put 50 pop_min 50 upgrade
heap 166_808 5_697_879_935 29_995_956 621_338 228_674 592_198 3_309_814_038
heap_rs 459_314 138_669_874 18_219_008 57_563 23_345 57_695 511_961_183

Growable array

binary_size generate 5k max mem batch_get 500 batch_put 500 batch_remove 500 upgrade
buffer 173_215 2_570_947 65_644 95_490 800_452 170_490 3_061_307
vector 171_563 1_920_997 24_580 126_114 183_385 175_981 4_695_522
vec_rs 453_413 289_090 1_310_720 17_298 30_623 25_758 3_171_665

Stable structures

binary_size generate 50k max mem batch_get 50 batch_put 50 batch_remove 50 upgrade
btreemap_rs 471_597 76_392_040 2_490_368 65_130 97_326 85_331 126_467_332
btreemap_stable_rs 483_530 5_255_631_698 2_031_616 3_167_240 5_784_534 9_888_430 731_136
heap_rs 459_314 7_001_770 2_228_224 50_072 23_593 50_044 26_819_689
heap_stable_rs 444_563 319_633_532 458_752 2_674_735 278_363 2_654_537 731_285
vec_rs 453_413 3_079_434 2_228_224 17_298 18_473 17_999 24_772_181
vec_stable_rs 441_204 75_145_327 458_752 71_671 91_519 94_915 731_270

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0

    Cryptographic libraries

Measure different cryptographic libraries written in both Motoko and Rust.

SHA-2

binary_size SHA-256 SHA-512 account_id neuron_id
Motoko 195_805 273_037_084 259_835_224 34_373 24_897
Rust 476_042 82_788_038 56_793_082 48_636 51_163

Certified map

binary_size generate 10k max mem inc witness upgrade
Motoko 244_500 4_763_348_103 3_430_044 565_117 402_073 274_275_937
Rust 498_197 6_309_529_789 2_228_224 1_004_188 301_339 5_926_705_684

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0

    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 upgrade
Motoko 274_773 510_733 22_316 18_548 19_597 157_638
Rust 778_222 611_282 101_374 125_148 137_434 1_816_495

DIP721 NFT

binary_size init mint_token transfer_token upgrade
Motoko 221_922 481_158 29_810 8_776 89_459
Rust 790_671 239_293 368_586 89_013 2_001_978

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0

    Heartbeat / Timer

Measure the cost of empty heartbeat and timer job.

Heartbeat

binary_size heartbeat
Motoko 137_205 23_182
Rust 23_873 1_172

Timer

binary_size setTimer cancelTimer
Motoko 145_582 51_467 4_610
Rust 420_710 68_153 11_161

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0

    Motoko Specific Benchmarks

Measure various features only available in Motoko.

Garbage Collection

generate 700k max mem batch_get 50 batch_put 50 batch_remove 50
default 1_171_395_786 51_991_392 119 119 119
copying 1_171_395_668 51_991_392 1_171_104_136 1_171_195_696 1_171_106_949
compacting 1_672_114_659 51_991_392 1_290_052_154 1_533_417_828 1_564_512_242
generational 2_529_073_372 51_999_856 999_515_201 1_232_740 1_103_853
incremental 29_503_138 985_890_580 333_755_986 336_886_802 336_875_628

Actor class

binary size put new bucket put existing bucket get
Map 299_052 813_512 16_099 16_644

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0

    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 161_257 145_541 28_593 11_963 22_864 6_430
Rust 456_613 507_753 69_189 42_865 92_768 52_116

Environment

  • dfx 0.15.2-beta.1
  • Motoko compiler 0.10.2 (source vy3jgjpa-6ywclfhp-r10kgfpz-gkw93wh8)
  • rustc 1.73.0 (cc66ad468 2023-10-03)
  • ic-repl 0.6.0
  • ic-wasm 0.7.0