Choix de la machine de référence pour l'étalonnage des poids

Dans substrate, chaque extrinsic doit se voir assigner une fonction qui calcule le temps d’exécution théorique de l’extrinsic en fonction de ses paramètres d’entrée. Ce temps est quantifié en poids, avec 1 poid = 10^-12 seconde.

Pour créer cette fonction, on code des benchmarks, qui doivent être exécutés sur une machine de référence.

Le jour ou la charge sur la blockchain Ğ1 sera proche de ses capacités maximales, tous les nœuds duniter-v2s devront impérativement avoir des spécifications matérielles supérieures où égales à la machine de référence.

En effet, si un nœud à des spécifications matérielles plus faible, et qu’il lui faut donc plus de temps pour exécuter les blocs, il risque de se désynchroniser du réseau si les blocs sont bien remplis.

Sauf spam, dont il faudra se protéger par des quotas ou/et frais, je pense qu’on aura encore de longues années devant nous avant de s’approcher de la capacité maximale de la nouvelle blockchain Ğ1 qui sera propulsée par Duniter-v2s.

Cependant, on doit quand même faire un étalonnage des poids avant de migrer la Ğ1, et pour cela on doit choisir une machine de référence, donc les capacités fixeront directement les capacités maximales de la blockchain.

J’ai une seule contrainte: il faut que cette machine de référence soit accessible en ssh par les développeurs de duniter-v2s afin qu’ils puissent travailler dessus pour coder et exécuter les benchmarks.

Pour information, voici les spécifications de références utilisées par Polkadot:

On peut partir sur plus modeste, mais la capacité maximale de notre blockchain en sera réduite, et la relation n’est pas forcément linéaire, on ne le saura que quand on aura fait les benchmarks.

Le choix que nous ferons n’a aucune obligation d’être définitif. On peut à tout moment décider de changer de machine de référence, mais les gestionnaires de nœuds devront continuer de se conformer à l’ancienne machine de référence pendant quelques mois, le temps que l’on puisse rejouer tous les benchmarks, vérifier les résultats, puis proposer un runtime upgrade onchain.

3 Likes

Le plus important c’est d’être sur SSD, et si possible en NVME, car le plus gros des traitements lors de l’exécution d’un bloc c’est les lectures/écritures dans le storage onchain.

Il n’y a pas de calculs coûteux onchain, donc le cpu à peu d’impact.

Quant à la RAM, elle permet de mettre en cache les clés du storage qui ont déjà été lues, donc ça optimise dans les cas où on lit une même clé plusieurs fois dans un bloc, mais je pense que la aussi c’est quasi négligeable, et en tous les cas en avoir plus ne sert pas à grand-chose

Le seul facteur vraiment limitant, c’est le temps d’accès à la base de donnée pour lire et écrire dans le storage onchain.

Il faut également savoir que substrate utilise une base de donnée optimisée pour les SSD, donc ce qui est certain à minima c’est qu’il faudra proscrire les HDD.

Pour que suffisamment de personnes puissent contribuer, il faudrait que le minimum requis soit du niveau d’un RPi3 avec un SSD en USB2 (ou RPi4 avec USB3 si c’est trop lent), ou d’un VPS SSD premier prix. Si c’est comme pour Polkadot un serveur à 80€/mois on ne peut pas parler de commun…

Concernant les RPi, j’y suis plutôt opposé à cause de leur architecture arm.
Substrate n’est pas conçu pour fonctionner sur arm, et n’est pas utilisé en production dessus, donc on n’a aucune garantie que ça puisse bien fonctionner et je ne ferai pas courir ce risque technique à la Ğ1.

Tant que c’est une architecture x86_64, on peut envisager une machine de référence très modeste, mais Il faut voir à quel point ça réduit les capacités de la blockchain, nous devons choisir un compromis entre capacité maximale de notre blockchain et facilité à pouvoir créer des blocs, c’est un choix collectif à faire en fonction de ce que nous voulons pour la Ğ1 :slight_smile:

Personnellement, j’aimerais bien qu’on soit à minima en capacité de supporter 1 million de membres, car @Galuel disais que c’est à partir de cette taille-là qu’une zone économique produit une diversité de biens et services satisfaisante.

Il faut qu’on se fixe des hypothèses, du genre combien de transactions par jour doit pouvoir faire un utilisateur en moyenne dans le cadre d’un usage quotidien (donc beaucoup plus qu’aujourd’hui).

En fait je me dis qu’il faut que la rémunération des créateurs de bloc couvre à minima les frais liés au matériel qu’il mette à disposition pour ce faire.

Or plus nous seront nombreux plus la rémunération en Ğ1 permettra facilement de compenser les frais en UNL.

Donc on peut très bien décider de commencer avec une machine de référence qui ne supporte pas le million de membres mais qui est peu coûteuse, en décidant dès à présent que l’on augmentera les spec de cette machine de référence lorsque nous aurons atteint un certain seuil d’utilisateurs :slight_smile:

En revanche, pour la fiabilité et la reproductabilité des benchmarks, la machine de référence ne peut pas être une VM, car les ressources dont dispose cette VM dépendent de ce que font les autres VM qui partagent les mêmes ressources matérielles. Il faut que ce soit une vraie machine physique.

Je peux acheter un mini pc en x86 le moins cher possible, on en trouve à moins de 200 UNL, puis jouer les benchmarks dessus pour voir ce que ça donne, mais ces derniers ne sont pas encore codés, donc ce ne sera pas pour tout de suite.

On a encore le temps pour voir ça, mais j’en parle dès maintenant car j’ai fait plusieurs fois allusion à cette machine de référence dans d’autres sujets, donc il fallait que j’en parle.

1 Like

Suite à des tests concluants sur armv7, je propose très officiellement de définir le « Raspberry Pi 4 Model B - 4GB - SSD USB3 » comme machine de référence.

Du moins dans un 1er temps, car cela va fortement nous limiter en taille de blocs, donc d’ici quelques années nous auront probablement besoin de passer sur une machine de référence plus puissante.

J’ai passé le week-end à mettre en place la structure pour le « weights benchmarking », afin de pouvoir mesurer concrètement quelle taille de bloc nous pourront avoir sur raspberry pi 4.

Pour le moment je n’ai pu benchmarker que les simples transferts de monnaie, mais ça donne déjà un ordre d’idée: j’obtiens des performances à peu près 50 fois plus faible que la machine de référence de Polkadot.

Plus concrètement, on sera limité à 400* transfers de monnaie par bloc, si le bloc ne contient que ça, donc aucune certif ni aucune création de DU ni rien d’autre.
Tant qu’on est en dessous de 100 000 utilisateurs ça devrait être suffisant, et l’idée c’est qu’au-delà on aura les moyens de mieux rémunérer les forgerons pour qu’ils puissent investir dans du matériel plus conséquent.

*Calcul du nombre max de transferts par bloc

On se base sur le call balances.transfer_keep_alive qui est le call qui sera utilisé dans la pratique par les wallet, en plus il est moins coûteux que balances.transfer.

D’après le benchmarking, le poids de ce call est 1_414_318_000 + 1 read + 2 writes.
Il faut également ajouter le poids de base d’un extrinsic:

 base_extrinsic: 1 billion
 read: 250 millions
 write: 1 billion
 transfer_keep_alive: 1_414_318_000 + 1 read + 2 writes + base = 1_414_318_000 + 2.25 billions + 1 milliard = 3_664_318_000 ~= 3.66 billions.
normal.max_block: 1500 billions
normal.max_block / transfer_keep_alive = 1500 / 3.66 = 409

On tombe bien sur environ 400 transferts.

Pour ceux qui souhaitent plus de détails, voici la MR:

4 Likes

Je précise que le raspberry pi 4 doit impérativement être équipé d’un disque SSD connecté en USB3, et que de data-dir de duniter-v2s doit être sur le SSD.

Les DB utilisées par substrate que ce soit RocksDB ou ParityDB, ont toutes deux été conçues et optimisées pour SSD, tout nœud substrate doit fonctionner exclusivement sur SSD.

1 Like

J’ai compilé elois-runtime-benchmarks-1 sur mon RPi mais un truc ne passe pas :

cargo build --target=armv7-unknown-linux-gnueabihf --release --features runtime-benchmarks
./target/armv7-unknown-linux-gnueabihf/release/duniter benchmark --chain=dev --steps=50 --repeat=20 --pallet=pallet_universal_dividend --extrinsic=* --execution=wasm --wasm-execution=compiled --heap-pages=4096 --header=./file_header.txt --output=.

Erreur :

error: "compiled" isn't a valid value for '--wasm-execution <METHOD>'
	[possible values: interpreted-i-know-what-i-do]

Ça ne marche qu’en cross-compilation, pas directement sur le Pi ?

Si ça marche, mais tu n’as pas lu la doc en entier:

Note2: If the reference machine not support wasmtime, you should replace --wasm-execution=compiled by --wasm-execution=interpreted-i-know-what-i-do.

2 Likes

Ok j’obtiens des poids proches des tiens (un peu inférieurs probablement parce que le serveur est utilisé par d’autres services).

3 Likes