iota_single_node_benchmark/
command.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::path::PathBuf;
6
7use clap::{Parser, Subcommand, ValueEnum};
8use strum::EnumIter;
9
10#[derive(Parser)]
11#[command(
12    name = "iota-single-node-benchmark",
13    about = "Benchmark a single validator node",
14    author,
15    version
16)]
17pub struct Command {
18    #[arg(
19        long,
20        default_value_t = 500000,
21        help = "Number of transactions to submit"
22    )]
23    pub tx_count: u64,
24    #[arg(
25        long,
26        default_value_t = 100,
27        help = "Number of transactions in a consensus commit/checkpoint"
28    )]
29    pub checkpoint_size: usize,
30    #[arg(
31        long,
32        help = "Whether to print out a sample transaction and effects that is going to be benchmarked on"
33    )]
34    pub print_sample_tx: bool,
35    #[arg(
36        long,
37        default_value_t = false,
38        help = "If true, skip signing on the validators, instead, creating certificates directly using validator secrets"
39    )]
40    pub skip_signing: bool,
41    #[arg(
42        long,
43        default_value = "baseline",
44        ignore_case = true,
45        help = "Which component to benchmark"
46    )]
47    pub component: Component,
48    #[command(subcommand)]
49    pub workload: WorkloadKind,
50}
51
52#[derive(Copy, Clone, EnumIter, ValueEnum)]
53pub enum Component {
54    ExecutionOnly,
55    /// Baseline includes the execution and storage layer only.
56    Baseline,
57    /// On top of Baseline, this schedules transactions through the transaction
58    /// manager.
59    WithTxManager,
60    /// This goes through the `handle_certificate` entry point on
61    /// authority_server, which includes certificate verification,
62    /// transaction manager, as well as a noop consensus layer. The noop
63    /// consensus layer does absolutely nothing when receiving a transaction in
64    /// consensus.
65    ValidatorWithoutConsensus,
66    /// Similar to ValidatorWithNoopConsensus, but the consensus layer contains
67    /// a fake consensus protocol that basically sequences transactions in
68    /// order. It then verify the transaction and store the sequenced
69    /// transactions into the store. It covers the consensus-independent
70    /// portion of the code in consensus handler.
71    ValidatorWithFakeConsensus,
72    /// Benchmark only validator signing component: `handle_transaction`.
73    TxnSigning,
74    /// Benchmark the checkpoint executor by constructing a full epoch of
75    /// checkpoints, execute all transactions in them and measure time.
76    CheckpointExecutor,
77}
78
79#[derive(Subcommand, Clone)]
80pub enum WorkloadKind {
81    PTB {
82        #[arg(
83            long,
84            default_value_t = 0,
85            help = "Number of address owned input objects per transaction.\
86                This represents the amount of DB reads per transaction prior to execution."
87        )]
88        num_transfers: u64,
89        #[arg(
90            long,
91            default_value_t = false,
92            help = "When transferring an object, whether to use native TransferObjecet command, or to use Move code for the transfer"
93        )]
94        use_native_transfer: bool,
95        #[arg(
96            long,
97            default_value_t = 0,
98            help = "Number of dynamic fields read per transaction.\
99            This represents the amount of runtime DB reads per transaction during execution."
100        )]
101        num_dynamic_fields: u64,
102        #[arg(
103            long,
104            default_value_t = 0,
105            help = "Computation intensity per transaction.\
106            The transaction computes the n-th Fibonacci number \
107            specified by this parameter * 100."
108        )]
109        computation: u8,
110        #[arg(
111            long,
112            default_value_t = 0,
113            help = "Whether to use shared objects in the transaction.\
114            If 0, no shared objects will be used.\
115            Otherwise `v` shared objects will be created and each transaction will use these `v` shared objects."
116        )]
117        num_shared_objects: usize,
118        #[arg(
119            long,
120            default_value_t = 0,
121            help = "How many NFTs to mint/transfer during the transaction.\
122            If 0, no NFTs will be minted.\
123            Otherwise `v` NFTs with the specified size will be created and transferred to the sender"
124        )]
125        num_mints: u16,
126        #[arg(
127            long,
128            default_value_t = 32,
129            help = "Size of the Move contents of the NFT to be minted, in bytes.\
130            Defaults to 32 bytes (i.e., NFT with ID only)."
131        )]
132        nft_size: u16,
133        #[arg(
134            long,
135            help = "If true, call a single batch_mint Move function.\
136            Otherwise, batch via a PTB with multiple commands"
137        )]
138        use_batch_mint: bool,
139    },
140    Publish {
141        #[arg(
142            long,
143            help = "Path to the manifest file that describe the package dependencies.\
144            Follow examples in the tests directory to see how to set up the manifest file.\
145            The manifest file is a json file that contains a list of dependent packages that need to\
146            be published first, as well as the root package that will be benchmarked on. Each package\
147            can be either in source code or bytecode form. If it is in source code form, the benchmark\
148            will compile the package first before publishing it."
149        )]
150        manifest_file: PathBuf,
151    },
152}
153
154impl WorkloadKind {
155    pub(crate) fn gas_object_num_per_account(&self) -> u64 {
156        match self {
157            // Each transaction will always have 1 gas object, plus the number of owned objects that
158            // will be transferred.
159            WorkloadKind::PTB { num_transfers, .. } => *num_transfers + 1,
160            WorkloadKind::Publish { .. } => 1,
161        }
162    }
163}