diff --git a/Builds/VisualStudio/stellar-core.vcxproj b/Builds/VisualStudio/stellar-core.vcxproj index 55e855a360..d2e4460c2e 100644 --- a/Builds/VisualStudio/stellar-core.vcxproj +++ b/Builds/VisualStudio/stellar-core.vcxproj @@ -596,6 +596,7 @@ exit /b 0 + @@ -603,7 +604,6 @@ exit /b 0 - @@ -670,6 +670,7 @@ exit /b 0 + @@ -1060,6 +1061,7 @@ exit /b 0 + @@ -1069,7 +1071,6 @@ exit /b 0 - @@ -1119,6 +1120,7 @@ exit /b 0 + diff --git a/Builds/VisualStudio/stellar-core.vcxproj.filters b/Builds/VisualStudio/stellar-core.vcxproj.filters index be47043482..cd153ba742 100644 --- a/Builds/VisualStudio/stellar-core.vcxproj.filters +++ b/Builds/VisualStudio/stellar-core.vcxproj.filters @@ -1314,9 +1314,6 @@ main - - ledger - main @@ -1438,6 +1435,12 @@ util + + ledger + + + test + @@ -2427,9 +2430,6 @@ main - - ledger - main @@ -2554,6 +2554,12 @@ util + + ledger + + + test + diff --git a/docs/apply-load-for-meta.cfg b/docs/apply-load-for-meta.cfg index bdcda5dd65..2a1c5a3f09 100644 --- a/docs/apply-load-for-meta.cfg +++ b/docs/apply-load-for-meta.cfg @@ -15,44 +15,39 @@ METADATA_OUTPUT_STREAM='meta.xdr' # Network configuration to use during the benchmark # The fields here correspond to the network configuration settings. -APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS = 500000000 -APPLY_LOAD_TX_MAX_INSTRUCTIONS = 100000000 +APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS = 580000000 +APPLY_LOAD_TX_MAX_INSTRUCTIONS = 400000000 -APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 1 +APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 2 -APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE = 200 +APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE = 400 APPLY_LOAD_LEDGER_MAX_DISK_READ_LEDGER_ENTRIES = 1000 -APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 100 +APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 200 -APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 200000 -APPLY_LOAD_TX_MAX_DISK_READ_BYTES = 130000 +APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 400000 +APPLY_LOAD_TX_MAX_DISK_READ_BYTES = 200000 APPLY_LOAD_LEDGER_MAX_WRITE_LEDGER_ENTRIES = 1000 -APPLY_LOAD_TX_MAX_WRITE_LEDGER_ENTRIES = 100 +APPLY_LOAD_TX_MAX_WRITE_LEDGER_ENTRIES = 200 -APPLY_LOAD_LEDGER_MAX_WRITE_BYTES = 300000 -APPLY_LOAD_TX_MAX_WRITE_BYTES = 140000 +APPLY_LOAD_LEDGER_MAX_WRITE_BYTES = 286720 +APPLY_LOAD_TX_MAX_WRITE_BYTES = 132096 -APPLY_LOAD_MAX_LEDGER_TX_SIZE_BYTES = 270000 -APPLY_LOAD_MAX_TX_SIZE_BYTES = 150000 +APPLY_LOAD_MAX_LEDGER_TX_SIZE_BYTES = 266240 +APPLY_LOAD_MAX_TX_SIZE_BYTES = 132096 -APPLY_LOAD_MAX_CONTRACT_EVENT_SIZE_BYTES = 10000 -APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 1000 +APPLY_LOAD_MAX_CONTRACT_EVENT_SIZE_BYTES = 16384 +APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 482 # The following section contains various parameters for the generated load. -# Number of ledgers to close for benchmark +# Number of ledgers to close for the benchmark. APPLY_LOAD_NUM_LEDGERS = 100 # Generate that many simple Classic payment transactions in every benchmark ledger APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 1000 -# Size of every synthetic data entry generated. -# This setting affects both the size of the pre-generated Bucket List entries, -# and the size of every entry that a Soroban transaction reads/writes. -APPLY_LOAD_DATA_ENTRY_SIZE = 300 - # Bucket list pre-generation # The benchmark will pre-generate ledger entries using the simplified ledger @@ -78,44 +73,11 @@ APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 #APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 #APPLY_LOAD_BL_LAST_BATCH_SIZE = 100 -# Settings for generated transactions -# Every setting consists of the list of the possible values and the respective -# _DISTRIBUTION list that defines the weight of every value. The values are then -# sampled from the value list according to the distribution. - -# Core will try to pack as many generated transactions as possible, -# so if it's important to maintain a constant number of transactions per ledger, -# or to maintain constant utilization of every resources dimension in every -# ledger, then sampling should be avoided. - -# It's generally a good idea to utilize as many dimensions as possible, so -# the values here should be chosen carefully such that the ratio between the -# generated value and the respective limit is the roughly same for most of the -# resources. - -# Number of *disk* reads a transaction performs. Every disk read is restoration, -# so it's also a write (accounted for in NUM_RW_ENTRIES). -APPLY_LOAD_NUM_DISK_READ_ENTRIES = [1] -APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = [1] - -# Number of writes a transaction performs. -APPLY_LOAD_NUM_RW_ENTRIES = [4] -APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = [1] - -# Number of events a transaction emits. +# Number of events a transaction emits and the respective distribution weights. APPLY_LOAD_EVENT_COUNT = [5] APPLY_LOAD_EVENT_COUNT_DISTRIBUTION = [1] -# Size of the generated transaction. -APPLY_LOAD_TX_SIZE_BYTES = [1080] -APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = [1] - -# Number of instructions a transaction will use. -APPLY_LOAD_INSTRUCTIONS = [2000000] -APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = [1] - # Common apply load boilerplate - ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true # Diagnostic events should generally be disabled, but can be enabled for debug ENABLE_SOROBAN_DIAGNOSTIC_EVENTS = false diff --git a/docs/apply-load-ledger-limits.cfg b/docs/apply-load-ledger-limits.cfg index 6e244adf4e..cdd321e43b 100644 --- a/docs/apply-load-ledger-limits.cfg +++ b/docs/apply-load-ledger-limits.cfg @@ -19,46 +19,39 @@ METADATA_DEBUG_LEDGERS = 0 # Network configuration to use during the benchmark # The fields here correspond to the network configuration settings. -APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS = 500000000 -APPLY_LOAD_TX_MAX_INSTRUCTIONS = 100000000 +APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS = 580000000 +APPLY_LOAD_TX_MAX_INSTRUCTIONS = 400000000 -APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 1 +APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 2 -APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE = 200 +APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE = 400 APPLY_LOAD_LEDGER_MAX_DISK_READ_LEDGER_ENTRIES = 1000 -APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 100 +APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 200 -APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 150000 -APPLY_LOAD_TX_MAX_DISK_READ_BYTES = 130000 +APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 400000 +APPLY_LOAD_TX_MAX_DISK_READ_BYTES = 200000 APPLY_LOAD_LEDGER_MAX_WRITE_LEDGER_ENTRIES = 1000 -APPLY_LOAD_TX_MAX_WRITE_LEDGER_ENTRIES = 100 +APPLY_LOAD_TX_MAX_WRITE_LEDGER_ENTRIES = 200 -APPLY_LOAD_LEDGER_MAX_WRITE_BYTES = 300000 -APPLY_LOAD_TX_MAX_WRITE_BYTES = 140000 +APPLY_LOAD_LEDGER_MAX_WRITE_BYTES = 286720 +APPLY_LOAD_TX_MAX_WRITE_BYTES = 132096 -APPLY_LOAD_MAX_LEDGER_TX_SIZE_BYTES = 270000 -APPLY_LOAD_MAX_TX_SIZE_BYTES = 150000 +APPLY_LOAD_MAX_LEDGER_TX_SIZE_BYTES = 266240 +APPLY_LOAD_MAX_TX_SIZE_BYTES = 132096 -APPLY_LOAD_MAX_CONTRACT_EVENT_SIZE_BYTES = 10000 -APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 1000 +APPLY_LOAD_MAX_CONTRACT_EVENT_SIZE_BYTES = 16384 +APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 482 # The following section contains various parameters for the generated load. -# Maximum number of ledgers to close for every iteration of search. -# Should be at least 30 and normally doesn't need to be changed as search will -# not run extra iterations if the results are already statistically significant. -APPLY_LOAD_NUM_LEDGERS = 1000 +# Number of ledgers to close for the benchmark. +APPLY_LOAD_NUM_LEDGERS = 100 # Generate that many simple Classic payment transactions in every benchmark ledger APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 0 -# Size of every synthetic data entry generated. -# This setting affects both the size of the pre-generated Bucket List entries, -# and the size of every entry that a Soroban transaction reads/writes. -APPLY_LOAD_DATA_ENTRY_SIZE = 300 - # Bucket list pre-generation # The benchmark will pre-generate ledger entries using the simplified ledger @@ -84,42 +77,10 @@ APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 #APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 #APPLY_LOAD_BL_LAST_BATCH_SIZE = 100 -# Settings for generated transactions -# Every setting consists of the list of the possible values and the respective -# _DISTRIBUTION list that defines the weight of every value. The values are then -# sampled from the value list according to the distribution. - -# Core will try to pack as many generated transactions as possible, -# so if it's important to maintain a constant number of transactions per ledger, -# or to maintain constant utilization of every resources dimension in every -# ledger, then sampling should be avoided. - -# It's generally a good idea to utilize as many dimensions as possible, so -# the values here should be chosen carefully such that the ratio between the -# generated value and the respective limit is the roughly same for most of the -# resources. - -# Number of *disk* reads a transaction performs. Every disk read is restoration, -# so it's also a write (accounted for in NUM_RW_ENTRIES). -APPLY_LOAD_NUM_DISK_READ_ENTRIES = [2] -APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = [1] - -# Number of writes a transaction performs. -APPLY_LOAD_NUM_RW_ENTRIES = [4] -APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = [1] - -# Number of events a transaction emits. +# Number of events a transaction emits and the respective distribution weights. APPLY_LOAD_EVENT_COUNT = [5] APPLY_LOAD_EVENT_COUNT_DISTRIBUTION = [1] -# Size of the generated transaction. -APPLY_LOAD_TX_SIZE_BYTES = [1080] -APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = [1] - -# Number of instructions a transaction will use. -APPLY_LOAD_INSTRUCTIONS = [2000000] -APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = [1] - # Common apply load boilerplate ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true # Diagnostic events should generally be disabled, but can be enabled for debug diff --git a/docs/apply-load-limits-for-model-tx.cfg b/docs/apply-load-limits-for-model-tx.cfg deleted file mode 100644 index c532091add..0000000000 --- a/docs/apply-load-limits-for-model-tx.cfg +++ /dev/null @@ -1,128 +0,0 @@ -# This is the Stellar Core configuration example for using the load generation -# (apply-load) tool for finding the maximum ledger limits by applying a number -# of the equivalent 'model' transactions. -# -# The mode will find the maximum value of N, such that closing a ledger -# with N 'model' transactions takes less than a certain target time. Then -# it will find the actual ledger limits by multiplying the 'model' transaction -# dimensions by N. -# -# This is not meant to be used in any production contexts. -# -# The core with this configuration should be run using `./stellar-core apply-load` - -# Select the apply-load mode. -APPLY_LOAD_MODE="limits-for-model-tx" - -# Medida metrics (histograms in particular) in apply path cause severe and -# non-deterministic performance degradation. While this has to be addressed -# eventually, it is useful to disable these when optimizing anything besides -# the metrics. -DISABLE_SOROBAN_METRICS_FOR_TESTING = false -# Disable metadata output -METADATA_OUTPUT_STREAM = "" -# Disable metadata debug -METADATA_DEBUG_LEDGERS = 0 - -# Target average ledger close time. -APPLY_LOAD_TARGET_CLOSE_TIME_MS = 300 - -# Network configuration section - -# Most of the network configuration will be inferred automatically from the 'model' -# transaction (for transaction limits) and from the search itself (for the ledger) -# limits. Only the following limits need to be set: - -# In this mode, defines the search upper bound for the number of Soroban -# transactions to apply. -APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 2000 - -# Number of the transaction clusters and thus apply threads. This will stay constant -# during the search, unlike all the other ledger limits. -APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 8 - -# The following section contains various parameters for the generated load. - -# Maximum number of ledgers to close for every iteration of search. -# Should be at least 30 and normally doesn't need to be changed as search will -# not run extra iterations if the results are already statistically significant. -# The average close time will then be compared to APPLY_LOAD_TARGET_CLOSE_TIME_MS. -APPLY_LOAD_NUM_LEDGERS = 1000 - -# Generate that many simple Classic payment transactions in every benchmark ledger. -# Note, that this will affect the close time. -APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 0 - -# Size of every synthetic data entry generated. -# This setting affects both the size of the pre-generated Bucket List entries, -# and the size of every entry that a Soroban transaction reads/writes. -APPLY_LOAD_DATA_ENTRY_SIZE = 250 - -# Bucket list pre-generation - -# The benchmark will pre-generate ledger entries using the simplified ledger -# close process; the generated ledgers won't be reflected in the meta or -# history checkpoints. - -# Faster settings, more shallow BL (up to level 6) -# Number of ledgers to close -APPLY_LOAD_BL_SIMULATED_LEDGERS = 10000 -# Write a batch of entries every that many ledgers -APPLY_LOAD_BL_WRITE_FREQUENCY = 1000 -# Write that many entries in every batch -APPLY_LOAD_BL_BATCH_SIZE = 1000 -# Write entry batches in every ledger of this many last ledgers -APPLY_LOAD_BL_LAST_BATCH_SIZE = 100 -# Write that many entries in every 'last' ledger -APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 - -# Slower settings, deeper BL (up to level 9) -#APPLY_LOAD_BL_SIMULATED_LEDGERS = 300000 -#APPLY_LOAD_BL_WRITE_FREQUENCY = 10000 -#APPLY_LOAD_BL_BATCH_SIZE = 10000 -#APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300 -#APPLY_LOAD_BL_LAST_BATCH_SIZE = 100 - -# Settings for the generated 'model' transaction. -# Unlike the 'limit-based' apply-load mode, only a single value -# with `[1]` as distribution is allowed, thus only a single kind -# of transaction will be generated. - -# Number of *disk* reads a transaction performs. Every disk read is restoration, -# so it's also a write (accounted for in NUM_RW_ENTRIES). -APPLY_LOAD_NUM_DISK_READ_ENTRIES = [1] -APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = [1] - -# Number of writes a transaction performs. -APPLY_LOAD_NUM_RW_ENTRIES = [5] -APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = [1] - -# Number of 80-byte events a transaction emits. -APPLY_LOAD_EVENT_COUNT = [15] -APPLY_LOAD_EVENT_COUNT_DISTRIBUTION = [1] - -# Size of a generated transaction. -APPLY_LOAD_TX_SIZE_BYTES = [1650] -APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = [1] - -# Number of instructions a transaction will use. -APPLY_LOAD_INSTRUCTIONS = [4250000] -APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = [1] - - -# Common apply load boilerplate -ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true -# Diagnostic events should generally be disabled, but can be enabled for debug -ENABLE_SOROBAN_DIAGNOSTIC_EVENTS = false -# Set up plenty of genesis accounts - benchmark will fail if the number is not -# sufficient. This should be at least 2x of APPLY_LOAD_MAX_SOROBAN_TX_COUNT. -GENESIS_TEST_ACCOUNT_COUNT = 40000 - -# Minimal core config boilerplate - -UNSAFE_QUORUM=true -NODE_SEED="SDQVDISRYN2JXBS7ICL7QJAEKB3HWBJFP2QECXG7GZICAHBK4UNJCWK2 self" - -[QUORUM_SET] -THRESHOLD_PERCENT=100 -VALIDATORS=["$self"] diff --git a/docs/software/commands.md b/docs/software/commands.md index c4dde5790a..ad8218d318 100644 --- a/docs/software/commands.md +++ b/docs/software/commands.md @@ -34,12 +34,8 @@ Command options can only by placed after command. ledger close time for applying transactions. - `APPLY_LOAD_MODE="max-sac-tps"`: determines maximum TPS for the load consisting only of fast SAC transfer. - - `APPLY_LOAD_MODE="limits-for-model-tx"`: determines maximum ledger - limits for the load consisting only of a customizable 'model' - transaction. - `APPLY_LOAD_MODE="benchmark"`: benchmarks a fixed-size ledger of model - transactions. Use `APPLY_LOAD_MODEL_TX` to select the model transaction; - currently only `"sac"` is supported. + transactions. Use `APPLY_LOAD_MODEL_TX` to select the model transaction. * Load generation is configured in the Core config file. The relevant settings all begin with `APPLY_LOAD_`. See full example configurations with per-setting documentation in the `docs` directory diff --git a/src/main/Config.cpp b/src/main/Config.cpp index ed80271b39..fbaae88b36 100644 --- a/src/main/Config.cpp +++ b/src/main/Config.cpp @@ -415,17 +415,13 @@ parseApplyLoadMode(ConfigItem const& item) { return ApplyLoadMode::MAX_SAC_TPS; } - if (mode == "limits-for-model-tx") - { - return ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX; - } if (mode == "benchmark") { return ApplyLoadMode::BENCHMARK_MODEL_TX; } throw std::invalid_argument( "invalid 'APPLY_LOAD_MODE', expected one of: ledger-limits, " - "max-sac-tps, limits-for-model-tx, benchmark"); + "max-sac-tps, benchmark"); } ApplyLoadModelTx @@ -1686,16 +1682,6 @@ Config::processConfig(std::shared_ptr t) [&]() { APPLY_LOAD_MODE = parseApplyLoadMode(item); }}, {"APPLY_LOAD_MODEL_TX", [&]() { APPLY_LOAD_MODEL_TX = parseApplyLoadModelTx(item); }}, - {"APPLY_LOAD_DATA_ENTRY_SIZE", - [&]() { - APPLY_LOAD_DATA_ENTRY_SIZE = readInt(item); - // align to 4 bytes - if (APPLY_LOAD_DATA_ENTRY_SIZE % 4 != 0) - { - APPLY_LOAD_DATA_ENTRY_SIZE += - 4 - (APPLY_LOAD_DATA_ENTRY_SIZE % 4); - } - }}, {"APPLY_LOAD_BL_SIMULATED_LEDGERS", [&]() { APPLY_LOAD_BL_SIMULATED_LEDGERS = readInt(item); @@ -1714,43 +1700,6 @@ Config::processConfig(std::shared_ptr t) [&]() { APPLY_LOAD_BL_LAST_BATCH_SIZE = readInt(item); }}, - {"APPLY_LOAD_INSTRUCTIONS", - [&]() { - APPLY_LOAD_INSTRUCTIONS = readIntArray(item); - }}, - {"APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION", - [&]() { - APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = - readIntArray(item); - }}, - {"APPLY_LOAD_TX_SIZE_BYTES", - [&]() { - APPLY_LOAD_TX_SIZE_BYTES = readIntArray(item); - }}, - {"APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION", - [&]() { - APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = - readIntArray(item); - }}, - {"APPLY_LOAD_NUM_DISK_READ_ENTRIES", - [&]() { - APPLY_LOAD_NUM_DISK_READ_ENTRIES = - readIntArray(item); - }}, - {"APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION", - [&]() { - APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = - readIntArray(item); - }}, - {"APPLY_LOAD_NUM_RW_ENTRIES", - [&]() { - APPLY_LOAD_NUM_RW_ENTRIES = readIntArray(item); - }}, - {"APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION", - [&]() { - APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = - readIntArray(item); - }}, {"APPLY_LOAD_EVENT_COUNT", [&]() { APPLY_LOAD_EVENT_COUNT = readIntArray(item); diff --git a/src/main/Config.h b/src/main/Config.h index a718a8b843..3f214b615a 100644 --- a/src/main/Config.h +++ b/src/main/Config.h @@ -73,7 +73,6 @@ struct ValidatorWeightConfig enum class ApplyLoadMode { LIMIT_BASED, - FIND_LIMITS_FOR_MODEL_TX, MAX_SAC_TPS, BENCHMARK_MODEL_TX }; @@ -349,11 +348,6 @@ class Config : public std::enable_shared_from_this ApplyLoadMode APPLY_LOAD_MODE = ApplyLoadMode::LIMIT_BASED; ApplyLoadModelTx APPLY_LOAD_MODEL_TX = ApplyLoadModelTx::SAC; - // Size of the synthetic contract data entries used in apply-load. - // Currently we generate entries of the equal size for more precise - // control over the modelled instructions. - uint32_t APPLY_LOAD_DATA_ENTRY_SIZE = 0; - // The parameters below control the synthetic bucket list generation in // apply-load. @@ -400,34 +394,15 @@ class Config : public std::enable_shared_from_this uint32_t APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 1; // Number of ledgers to apply in apply-load. - // Depending on the mode this represents either the total number of ledgers - // to close for benchmarking, or the number of ledgers to apply per - // iteration of binary search for modes that perform search. uint32_t APPLY_LOAD_NUM_LEDGERS = 100; - // Target ledger close time in milliseconds for modes that perform binary - // search of TPS or limits. + // Target ledger close time in milliseconds for max-sac-tps mode. uint32_t APPLY_LOAD_TARGET_CLOSE_TIME_MS = 1000; // Number of classic transactions to include in each ledger in ledger limit // based apply-load mode. uint32_t APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 0; - // Number of instructions to generate in the apply-load transactions. - std::vector APPLY_LOAD_INSTRUCTIONS; - std::vector APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION; - - // Transaction size in bytes for the apply-load transactions. - std::vector APPLY_LOAD_TX_SIZE_BYTES; - std::vector APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION; - - // Number of disk read-only and read-write entries in the apply-load - // transactions. Every entry will have `APPLY_LOAD_DATA_ENTRY_SIZE` size. - std::vector APPLY_LOAD_NUM_DISK_READ_ENTRIES; - std::vector APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION; - std::vector APPLY_LOAD_NUM_RW_ENTRIES; - std::vector APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION; - // Number of events to generate in the apply-load transactions. std::vector APPLY_LOAD_EVENT_COUNT; std::vector APPLY_LOAD_EVENT_COUNT_DISTRIBUTION; diff --git a/src/simulation/ApplyLoad.cpp b/src/simulation/ApplyLoad.cpp index f881ef2d40..c9ad33d788 100644 --- a/src/simulation/ApplyLoad.cpp +++ b/src/simulation/ApplyLoad.cpp @@ -38,6 +38,13 @@ namespace { constexpr double NOISY_BINARY_SEARCH_CONFIDENCE = 0.99; +uint32_t +roundUpToXdrSizeMultiple(uint32_t size) +{ + uint32_t remainder = size % 4; + return remainder == 0 ? size : size + 4 - remainder; +} + void logExecutionEnvironmentSnapshot(Config const& cfg) { @@ -69,6 +76,81 @@ interpolatePercentile(std::vector const& sortedValues, return sortedValues[lo] * (1.0 - weight) + sortedValues[hi] * weight; } +template +void +throwIfResourceIsZero(T resourceVal, char const* resourceName) +{ + if (resourceVal == 0) + { + throw std::runtime_error(fmt::format( + FMT_STRING( + "Derived apply-load tx profile has zero {} in LIMIT_BASED " + "mode; reduce APPLY_LOAD_MAX_SOROBAN_TX_COUNT or raise " + "the corresponding ledger limit"), + resourceName)); + } +} + +ApplyLoadTxProfile +deriveLimitBasedTxProfile(ApplyLoadMode mode, Config const& cfg) +{ + if (mode != ApplyLoadMode::LIMIT_BASED) + { + return ApplyLoadTxProfile{}; + } + uint32_t txsPerLedger = cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT; + releaseAssert(txsPerLedger != 0); + + ApplyLoadTxProfile txProfile; + txProfile.instructions = std::min( + static_cast(cfg.APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS * + cfg.APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS / + txsPerLedger), + cfg.APPLY_LOAD_TX_MAX_INSTRUCTIONS); + throwIfResourceIsZero(txProfile.instructions, "instructions"); + + txProfile.txSizeBytes = + std::min(cfg.APPLY_LOAD_MAX_LEDGER_TX_SIZE_BYTES / txsPerLedger, + cfg.APPLY_LOAD_MAX_TX_SIZE_BYTES); + txProfile.txSizeBytes = roundUpToXdrSizeMultiple(txProfile.txSizeBytes); + throwIfResourceIsZero(txProfile.txSizeBytes, "tx-size bytes"); + + txProfile.rwEntries = + std::min({cfg.APPLY_LOAD_LEDGER_MAX_WRITE_LEDGER_ENTRIES / txsPerLedger, + cfg.APPLY_LOAD_TX_MAX_WRITE_LEDGER_ENTRIES, + cfg.APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE}); + throwIfResourceIsZero(txProfile.rwEntries, "rw entries"); + + // Base the data entry size on the write bytes limit, as normally the disk + // reads should mostly come from the restorations, and the restorations + // require write bytes. + txProfile.dataEntrySizeBytes = + std::min(cfg.APPLY_LOAD_LEDGER_MAX_WRITE_BYTES / + (txsPerLedger * txProfile.rwEntries), + cfg.APPLY_LOAD_TX_MAX_WRITE_BYTES / txProfile.rwEntries); + txProfile.dataEntrySizeBytes -= txProfile.dataEntrySizeBytes % 4; + throwIfResourceIsZero(txProfile.dataEntrySizeBytes, "data entry size"); + + txProfile.diskReadEntries = std::min( + {cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_LEDGER_ENTRIES / txsPerLedger, + cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES / + (txsPerLedger * txProfile.dataEntrySizeBytes), + cfg.APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES, txProfile.rwEntries}); + // Allow 0 disk read entries in case if we want to omit restorations. + + CLOG_INFO(Perf, + "Derived tx profile for {} txs per ledger: " + "instructions {}, tx size {}, disk read entries {}, disk read " + "bytes {}, rw entries {}, write bytes {}", + cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT, txProfile.instructions, + txProfile.txSizeBytes, txProfile.diskReadEntries, + txProfile.diskReadEntries * txProfile.dataEntrySizeBytes, + txProfile.rwEntries, + txProfile.rwEntries * txProfile.dataEntrySizeBytes); + + return txProfile; +} + SorobanUpgradeConfig getUpgradeConfig(Config const& cfg, bool validate = true) { @@ -509,51 +591,27 @@ ApplyLoad::getKeyForArchivedEntry(uint64_t index) } uint32_t -ApplyLoad::calculateRequiredHotArchiveEntries(ApplyLoadMode mode, - Config const& cfg) +ApplyLoad::getTotalHotArchiveEntries() const { - // If no RO entries are configured, return 0 - if (cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES.empty()) - { - return 0; - } + return mTotalHotArchiveEntries; +} - releaseAssertOrThrow( - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES.size() == - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION.size()); - - // Calculate mean disk reads per transaction - double totalWeight = std::accumulate( - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION.begin(), - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION.end(), 0.0); - double meanDiskReadsPerTx = 0.0; - for (size_t i = 0; i < cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES.size(); ++i) +uint32_t +ApplyLoad::calculateRequiredHotArchiveEntries(Config const& cfg) +{ + if (mMode != ApplyLoadMode::LIMIT_BASED) { - meanDiskReadsPerTx += - static_cast(cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES[i]) * - (cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION[i] / - totalWeight); + return 0; } // Calculate total expected disk reads - double totalExpectedRestores = meanDiskReadsPerTx * - cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT * - cfg.APPLY_LOAD_NUM_LEDGERS; + uint32_t totalExpectedRestores = mLimitsBasedTxProfile.diskReadEntries * + cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT * + cfg.APPLY_LOAD_NUM_LEDGERS; // We technically can only actually perform totalExpectedRestores, but we // still need to create valid transactions in the 'mempool', so we need // to scale the expected number of restores by the transaction queue size. totalExpectedRestores *= cfg.SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER; - - // In FIND_LIMITS_FOR_MODEL_TX mode, we perform a binary search that uses - // new restores and thus we need to additionally scale the restores by - // log2 of max tx count (which approximates the maximum number of binary - // search iterations). - if (mode == ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX) - { - totalExpectedRestores *= log2(cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT); - } - - // Add some generous buffer since actual distributions may vary. return totalExpectedRestores * 1.5; } @@ -561,8 +619,9 @@ ApplyLoad::ApplyLoad(Application& app) : mApp(app) , mMode(app.getConfig().APPLY_LOAD_MODE) , mModelTx(app.getConfig().APPLY_LOAD_MODEL_TX) + , mLimitsBasedTxProfile(deriveLimitBasedTxProfile(mMode, app.getConfig())) , mTotalHotArchiveEntries( - calculateRequiredHotArchiveEntries(mMode, app.getConfig())) + calculateRequiredHotArchiveEntries(app.getConfig())) , mTxCountUtilization( mApp.getMetrics().NewHistogram({"soroban", "apply-load", "tx-count"})) , mInstructionUtilization(mApp.getMetrics().NewHistogram( @@ -612,8 +671,7 @@ ApplyLoad::ApplyLoad(Application& app) } // Noisy binary search-based modes require at least 30 ledgers to have // enough samples for statistics to be meaningful. - if (mMode == ApplyLoadMode::MAX_SAC_TPS || - mMode == ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX) + if (mMode == ApplyLoadMode::MAX_SAC_TPS) { if (config.APPLY_LOAD_NUM_LEDGERS < 30) @@ -635,7 +693,6 @@ ApplyLoad::ApplyLoad(Application& app) switch (mMode) { case ApplyLoadMode::LIMIT_BASED: - case ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX: mNumAccounts = config.APPLY_LOAD_MAX_SOROBAN_TX_COUNT * config.SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER + config.APPLY_LOAD_CLASSIC_TXS_PER_LEDGER * @@ -724,7 +781,6 @@ ApplyLoad::setup() switch (mMode) { case ApplyLoadMode::LIMIT_BASED: - case ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX: setupLoadContract(); break; case ApplyLoadMode::MAX_SAC_TPS: @@ -752,7 +808,6 @@ ApplyLoad::setup() switch (mMode) { case ApplyLoadMode::MAX_SAC_TPS: - case ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX: // Just upgrade to a placeholder number of TXs, we'll // upgrade again before each TPS run. upgradeSettingsForMaxTPS(100000); @@ -766,8 +821,7 @@ ApplyLoad::setup() } // Setup initial bucket list for modes that support it. - if (mMode == ApplyLoadMode::LIMIT_BASED || - mMode == ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX) + if (mMode == ApplyLoadMode::LIMIT_BASED) { setupBucketList(); } @@ -836,9 +890,6 @@ ApplyLoad::execute() case ApplyLoadMode::MAX_SAC_TPS: findMaxSacTps(); break; - case ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX: - findMaxLimitsForModelTransaction(); - break; case ApplyLoadMode::BENCHMARK_MODEL_TX: benchmarkModelTx(); break; @@ -938,123 +989,6 @@ ApplyLoad::applyConfigUpgrade(SorobanUpgradeConfig const& upgradeConfig) 1); } -std::pair -ApplyLoad::updateSettingsForTxCount(uint64_t txsPerLedger) -{ - // Round the configuration values down to be a multiple of the respective - // step in order to get more readable configurations, and also to speeed - // up the binary search significantly. - uint64_t const INSTRUCTIONS_ROUNDING_STEP = 5'000'000; - uint64_t const SIZE_ROUNDING_STEP = 500; - uint64_t const ENTRIES_ROUNDING_STEP = 10; - - auto const& config = mApp.getConfig(); - uint64_t insns = - roundDown(txsPerLedger * config.APPLY_LOAD_INSTRUCTIONS[0] / - config.APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS, - INSTRUCTIONS_ROUNDING_STEP); - uint64_t txSize = roundDown( - txsPerLedger * config.APPLY_LOAD_TX_SIZE_BYTES[0], SIZE_ROUNDING_STEP); - - uint64_t writeEntries = - roundDown(txsPerLedger * config.APPLY_LOAD_NUM_RW_ENTRIES[0], - ENTRIES_ROUNDING_STEP); - uint64_t writeBytes = roundDown( - writeEntries * config.APPLY_LOAD_DATA_ENTRY_SIZE, SIZE_ROUNDING_STEP); - - uint64_t diskReadEntries = - roundDown(txsPerLedger * config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0], - ENTRIES_ROUNDING_STEP); - uint64_t diskReadBytes = - roundDown(diskReadEntries * config.APPLY_LOAD_DATA_ENTRY_SIZE, - SIZE_ROUNDING_STEP); - - if (diskReadEntries == 0) - { - diskReadEntries = - MinimumSorobanNetworkConfig::TX_MAX_READ_LEDGER_ENTRIES; - diskReadBytes = MinimumSorobanNetworkConfig::TX_MAX_READ_BYTES; - } - - uint64_t actualMaxTxs = txsPerLedger; - actualMaxTxs = - std::min(actualMaxTxs, - insns * config.APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS / - config.APPLY_LOAD_INSTRUCTIONS[0]); - actualMaxTxs = - std::min(actualMaxTxs, txSize / config.APPLY_LOAD_TX_SIZE_BYTES[0]); - if (config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0] > 0) - { - actualMaxTxs = std::min(actualMaxTxs, - diskReadEntries / - config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0]); - actualMaxTxs = std::min( - actualMaxTxs, - diskReadBytes / (config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0] * - config.APPLY_LOAD_DATA_ENTRY_SIZE)); - } - actualMaxTxs = std::min(actualMaxTxs, - writeEntries / config.APPLY_LOAD_NUM_RW_ENTRIES[0]); - - actualMaxTxs = std::min(actualMaxTxs, - writeBytes / (config.APPLY_LOAD_NUM_RW_ENTRIES[0] * - config.APPLY_LOAD_DATA_ENTRY_SIZE)); - CLOG_INFO(Perf, - "Resources after rounding for testing {} actual max txs per " - "ledger: " - "instructions {}, tx size {}, disk read entries {}, " - "disk read bytes {}, rw entries {}, rw bytes {}", - actualMaxTxs, insns, txSize, diskReadEntries, diskReadBytes, - writeEntries, writeBytes); - - auto upgradeConfig = getUpgradeConfig(mApp.getConfig(), - /* validate */ false); - // Set tx limits to the respective resources of the 'model' - // transaction. - upgradeConfig.txMaxInstructions = - std::max(MinimumSorobanNetworkConfig::TX_MAX_INSTRUCTIONS, - config.APPLY_LOAD_INSTRUCTIONS[0]); - upgradeConfig.txMaxSizeBytes = - std::max(MinimumSorobanNetworkConfig::TX_MAX_SIZE_BYTES, - config.APPLY_LOAD_TX_SIZE_BYTES[0]); - upgradeConfig.txMaxDiskReadEntries = - std::max(MinimumSorobanNetworkConfig::TX_MAX_READ_LEDGER_ENTRIES, - config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0]); - upgradeConfig.txMaxWriteLedgerEntries = - std::max(MinimumSorobanNetworkConfig::TX_MAX_WRITE_LEDGER_ENTRIES, - config.APPLY_LOAD_NUM_RW_ENTRIES[0]); - upgradeConfig.txMaxDiskReadBytes = - std::max(MinimumSorobanNetworkConfig::TX_MAX_READ_BYTES, - config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0] * - config.APPLY_LOAD_DATA_ENTRY_SIZE); - upgradeConfig.txMaxWriteBytes = - std::max(MinimumSorobanNetworkConfig::TX_MAX_WRITE_BYTES, - config.APPLY_LOAD_NUM_RW_ENTRIES[0] * - config.APPLY_LOAD_DATA_ENTRY_SIZE); - upgradeConfig.txMaxContractEventsSizeBytes = - std::max(MinimumSorobanNetworkConfig::TX_MAX_CONTRACT_EVENTS_SIZE_BYTES, - config.APPLY_LOAD_EVENT_COUNT[0] * - TxGenerator::SOROBAN_LOAD_V2_EVENT_SIZE_BYTES + - 100); - upgradeConfig.txMaxFootprintEntries = - *upgradeConfig.txMaxDiskReadEntries + - *upgradeConfig.txMaxWriteLedgerEntries; - - // Set the ledger-wide limits to the compute values calculated above. - // Note, that in theory we could end up with ledger limits lower than - // the transaction limits, but in normally would be just - // mis-configuration (using a model transaction that is too large to - // be applied within the target close time). - upgradeConfig.ledgerMaxInstructions = insns; - upgradeConfig.ledgerMaxTransactionsSizeBytes = txSize; - upgradeConfig.ledgerMaxDiskReadEntries = diskReadEntries; - upgradeConfig.ledgerMaxWriteLedgerEntries = writeEntries; - upgradeConfig.ledgerMaxDiskReadBytes = diskReadBytes; - upgradeConfig.ledgerMaxWriteBytes = writeBytes; - - return std::make_pair(upgradeConfig, actualMaxTxs); -} - void ApplyLoad::upgradeSettings() { @@ -1235,22 +1169,21 @@ ApplyLoad::setupBucketList() ContractDataDurability::PERSISTENT; baseLiveEntry.data.contractData().val.type(SCV_BYTES); - mDataEntrySize = xdr::xdr_size(baseLiveEntry); + auto dataEntrySize = xdr::xdr_size(baseLiveEntry); // Add some padding to reach the configured LE size. - if (mDataEntrySize < mApp.getConfig().APPLY_LOAD_DATA_ENTRY_SIZE) + if (dataEntrySize < mLimitsBasedTxProfile.dataEntrySizeBytes) { baseLiveEntry.data.contractData().val.bytes().resize( - mApp.getConfig().APPLY_LOAD_DATA_ENTRY_SIZE - mDataEntrySize); - mDataEntrySize = mApp.getConfig().APPLY_LOAD_DATA_ENTRY_SIZE; - releaseAssertOrThrow(xdr::xdr_size(baseLiveEntry) == mDataEntrySize); + mLimitsBasedTxProfile.dataEntrySizeBytes - dataEntrySize); + dataEntrySize = mLimitsBasedTxProfile.dataEntrySizeBytes; + releaseAssertOrThrow(xdr::xdr_size(baseLiveEntry) == dataEntrySize); } else { - CLOG_WARNING(Perf, - "Apply load generated entry size is larger than " - "APPLY_LOAD_DATA_ENTRY_SIZE: {} > {}", - mApp.getConfig().APPLY_LOAD_DATA_ENTRY_SIZE, - mDataEntrySize); + throw std::runtime_error(fmt::format( + "Apply load generated entry size is larger than " + "resolved apply-load data entry size: {} > {}", + dataEntrySize, mLimitsBasedTxProfile.dataEntrySizeBytes)); } auto logBucketListStats = [](std::string const& logStr, @@ -1273,6 +1206,12 @@ ApplyLoad::setupBucketList() // ledgers, but save one batch for the last batch to populate upper levels. uint32_t totalBatchCount = cfg.APPLY_LOAD_BL_SIMULATED_LEDGERS / cfg.APPLY_LOAD_BL_WRITE_FREQUENCY; + if (cfg.APPLY_LOAD_BL_SIMULATED_LEDGERS % + cfg.APPLY_LOAD_BL_WRITE_FREQUENCY != + 0) + { + totalBatchCount++; + } releaseAssertOrThrow(totalBatchCount > 0); // Reserve one batch worth of entries for the top level buckets. @@ -1560,7 +1499,7 @@ ApplyLoad::benchmarkLimitsIteration() auto [_, tx] = mTxGenerator.invokeSorobanLoadTransactionV2( lm.getLastClosedLedgerNum() + 1, it->first, mLoadInstance, - mDataEntryCount, mDataEntrySize, 1'000'000); + mLimitsBasedTxProfile, mDataEntryCount, 1'000'000); uint32_t ledgerVersion = mApp.getLedgerManager() .getLastClosedLedgerHeader() @@ -1610,116 +1549,6 @@ ApplyLoad::benchmarkLimitsIteration() return closeTime; } -void -ApplyLoad::findMaxLimitsForModelTransaction() -{ - auto const& config = mApp.getConfig(); - - auto validateTxParam = [&config](std::string const& paramName, - auto const& values, auto const& weights, - bool allowZeroValue = false) { - if (values.size() != 1) - { - throw std::runtime_error( - fmt::format(FMT_STRING("{} must have exactly one entry for " - "'limits-for-model-tx' mode"), - paramName)); - } - if (!allowZeroValue && values[0] == 0) - { - throw std::runtime_error(fmt::format( - FMT_STRING("{} cannot be zero for 'limits-for-model-tx' mode"), - paramName)); - } - if (weights.size() != 1 || weights[0] != 1) - { - throw std::runtime_error( - fmt::format(FMT_STRING("{}_DISTRIBUTION must have exactly one " - "entry with the value of 1 for " - "'limits-for-model-tx' mode"), - paramName)); - } - }; - validateTxParam("APPLY_LOAD_INSTRUCTIONS", config.APPLY_LOAD_INSTRUCTIONS, - config.APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION); - validateTxParam("APPLY_LOAD_TX_SIZE_BYTES", config.APPLY_LOAD_TX_SIZE_BYTES, - config.APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION); - validateTxParam("APPLY_LOAD_NUM_DISK_READ_ENTRIES", - config.APPLY_LOAD_NUM_DISK_READ_ENTRIES, - config.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION, true); - validateTxParam("APPLY_LOAD_NUM_RW_ENTRIES", - config.APPLY_LOAD_NUM_RW_ENTRIES, - config.APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION); - validateTxParam("APPLY_LOAD_EVENT_COUNT", config.APPLY_LOAD_EVENT_COUNT, - config.APPLY_LOAD_EVENT_COUNT_DISTRIBUTION, true); - - double targetTimeMs = mApp.getConfig().APPLY_LOAD_TARGET_CLOSE_TIME_MS; - - // Track the best config found during the search - SorobanUpgradeConfig maxLimitsConfig; - uint64_t maxLimitsTxsPerLedger = 0; - - auto prepareIteration = [this, &config](uint32_t testTxsPerLedger) { - CLOG_INFO(Perf, - "Testing ledger max model txs: {}, generated limits: " - "instructions {}, tx size {}, disk read entries {}, rw " - "entries {}", - testTxsPerLedger, - testTxsPerLedger * config.APPLY_LOAD_INSTRUCTIONS[0], - testTxsPerLedger * config.APPLY_LOAD_TX_SIZE_BYTES[0], - testTxsPerLedger * config.APPLY_LOAD_NUM_DISK_READ_ENTRIES[0], - testTxsPerLedger * config.APPLY_LOAD_NUM_RW_ENTRIES[0]); - - auto [upgradeConfig, actualMaxTxsPerLedger] = - updateSettingsForTxCount(testTxsPerLedger); - - applyConfigUpgrade(upgradeConfig); - }; - auto iterationResult = [this, &maxLimitsTxsPerLedger, &maxLimitsConfig]( - uint32_t testTxsPerLedger, bool isAbove) { - auto [upgradeConfig, actualMaxTxsPerLedger] = - updateSettingsForTxCount(testTxsPerLedger); - // Store the config if this is the best so far - if (!isAbove && actualMaxTxsPerLedger > maxLimitsTxsPerLedger) - { - maxLimitsTxsPerLedger = actualMaxTxsPerLedger; - maxLimitsConfig = upgradeConfig; - } - }; - - auto benchmarkFunc = [this](uint32_t testTxsPerLedger) -> double { - double closeTime = benchmarkLimitsIteration(); - releaseAssert(successRate() == 1.0); - return closeTime; - }; - - uint32_t minTxsPerLedger = 1; - uint32_t maxTxsPerLedger = mApp.getConfig().APPLY_LOAD_MAX_SOROBAN_TX_COUNT; - size_t maxSamplesPerPoint = mApp.getConfig().APPLY_LOAD_NUM_LEDGERS; - uint32_t xTolerance = 100; - - auto [lo, hi] = noisyBinarySearch( - benchmarkFunc, targetTimeMs, minTxsPerLedger, maxTxsPerLedger, - NOISY_BINARY_SEARCH_CONFIDENCE, xTolerance, maxSamplesPerPoint, - prepareIteration, iterationResult); - // Note, that the final search range may be above the TPL found, that's due - // to rounding we do when calculating TPL to benchmark (not every TPL - // value can be tested fairly). - CLOG_INFO(Perf, - "Maximum limits found for model transaction ({} TPL, [{}, {}] " - "final search range): " - "instructions {}, " - "tx size {}, disk read entries {}, disk read bytes {}, " - "write entries {}, write bytes {}", - maxLimitsTxsPerLedger, lo, hi, - *maxLimitsConfig.ledgerMaxInstructions, - *maxLimitsConfig.ledgerMaxTransactionsSizeBytes, - *maxLimitsConfig.ledgerMaxDiskReadEntries, - *maxLimitsConfig.ledgerMaxDiskReadBytes, - *maxLimitsConfig.ledgerMaxWriteLedgerEntries, - *maxLimitsConfig.ledgerMaxWriteBytes); -} - double ApplyLoad::successRate() { diff --git a/src/simulation/ApplyLoad.h b/src/simulation/ApplyLoad.h index 9dcc3788ca..d7b424ea97 100644 --- a/src/simulation/ApplyLoad.h +++ b/src/simulation/ApplyLoad.h @@ -44,10 +44,12 @@ class ApplyLoad // Returns LedgerKey for pre-populated archived state at the given index. static LedgerKey getKeyForArchivedEntry(uint64_t index); - static uint32_t calculateRequiredHotArchiveEntries(ApplyLoadMode mode, - Config const& cfg); + + uint32_t getTotalHotArchiveEntries() const; private: + uint32_t calculateRequiredHotArchiveEntries(Config const& cfg); + void setup(); void setupUpgradeContract(); void setupLoadContract(); @@ -63,18 +65,6 @@ class ApplyLoad // support metrics. void benchmarkLimits(); - // Runs for `execute() in `ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX` mode. - // Generates transactions according to the 'model' transaction parameters - // (specified via the transaction generation config), and does a binary - // search for the maximum number of such transactions that can fit into - // ledger while not exceeding APPLY_LOAD_TARGET_CLOSE_TIME_MS ledger close - // time. - // After finding the maximum number of model transactions, outputs the - // respective ledger limits. - // This also performs some rounding on the ledger limits to make the binary - // search faster, and also to produce more readable limits. - void findMaxLimitsForModelTransaction(); - // Runs for `execute() in `ApplyLoadMode::MAX_SAC_TPS` mode. // Generates SAC transactions and times just the application phase (fee and // sequence number processing, tx execution, and post process, but no disk @@ -146,22 +136,15 @@ class ApplyLoad // Helper method to apply a config upgrade void applyConfigUpgrade(SorobanUpgradeConfig const& upgradeConfig); - // Updates the configuration settings such a way to accommodate around - // `txsPerLedger` 'model' transactions per ledger for the - // `FIND_LIMITS_FOR_MODEL_TX` mode. - // Returns the network configuration to use for upgrade and the actual - // number of transactions that can fit withing the limits (it may be - // slightly lower than `txsPerLedger` due to rounding). - std::pair - updateSettingsForTxCount(uint64_t txsPerLedger); - Application& mApp; ApplyLoadMode mMode; ApplyLoadModelTx mModelTx; + ApplyLoadTxProfile mLimitsBasedTxProfile; - uint32_t mNumAccounts; uint32_t mTotalHotArchiveEntries; + uint32_t mNumAccounts; + medida::Histogram& mTxCountUtilization; medida::Histogram& mInstructionUtilization; medida::Histogram& mTxSizeUtilization; @@ -183,7 +166,6 @@ class ApplyLoad // Used for batch transfers, one instance for each cluster std::vector mBatchTransferInstances; size_t mDataEntryCount = 0; - size_t mDataEntrySize = 0; // Used to generate custom token transfer transactions TxGenerator::ContractInstance mTokenInstance; diff --git a/src/simulation/LoadGenerator.cpp b/src/simulation/LoadGenerator.cpp index 476fa9c5ac..eacec08204 100644 --- a/src/simulation/LoadGenerator.cpp +++ b/src/simulation/LoadGenerator.cpp @@ -162,10 +162,6 @@ LoadGenerator::getMode(std::string const& mode) { return LoadGenMode::PAY_PREGENERATED; } - else if (mode == "soroban_invoke_apply_load") - { - return LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD; - } else if (mode == "mixed_pregen_sac_payment") { return LoadGenMode::MIXED_PREGEN_SAC_PAYMENT; @@ -326,9 +322,7 @@ LoadGenerator::start(GeneratedLoadConfig& cfg) mClassicAppliedAtStart = getTxCount(mApp, /* isSoroban */ false); mSorobanAppliedAtStart = getTxCount(mApp, /* isSoroban */ true); - if ((cfg.mode == LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD || - cfg.modeMixesPregen()) && - !mApp.getRunInOverlayOnlyMode()) + if (cfg.modeMixesPregen() && !mApp.getRunInOverlayOnlyMode()) { reset(); throw std::runtime_error( @@ -641,9 +635,6 @@ GeneratedLoadConfig::getStatus() const case LoadGenMode::PAY_PREGENERATED: modeStr = "pay_pregenerated"; break; - case LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD: - modeStr = "SOROBAN_INVOKE_APPLY_LOAD"; - break; case LoadGenMode::MIXED_PREGEN_SAC_PAYMENT: modeStr = "mixed_pregen_sac_payment"; break; @@ -849,22 +840,6 @@ LoadGenerator::generateLoad(GeneratedLoadConfig cfg) case LoadGenMode::PAY_PREGENERATED: generateTx = [&]() { return readTransactionFromFile(cfg); }; break; - case LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD: - generateTx = [&]() { - auto instanceIter = mContractInstances.find(sourceAccountId); - releaseAssert(instanceIter != mContractInstances.end()); - auto const& instance = instanceIter->second; - auto const& appCfg = mApp.getConfig(); - uint64_t dataEntryCount = - appCfg.APPLY_LOAD_BL_BATCH_SIZE * - appCfg.APPLY_LOAD_BL_SIMULATED_LEDGERS; - size_t dataEntrySize = appCfg.APPLY_LOAD_DATA_ENTRY_SIZE; - - return mTxGenerator.invokeSorobanLoadTransactionV2( - ledgerNum, sourceAccountId, instance, dataEntryCount, - dataEntrySize, cfg.maxGeneratedFeeRate); - }; - break; case LoadGenMode::MIXED_PREGEN_SAC_PAYMENT: case LoadGenMode::MIXED_PREGEN_OZ_TOKEN_TRANSFER: case LoadGenMode::MIXED_PREGEN_SOROSWAP_SWAP: @@ -1581,9 +1556,6 @@ LoadGenerator::execute(TransactionFrameBasePtr txf, LoadGenMode mode, releaseAssert(false); } break; - case LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD: - txm.mSorobanInvokeTxs.Mark(); - break; case LoadGenMode::MIXED_PREGEN_SAC_PAYMENT: case LoadGenMode::MIXED_PREGEN_OZ_TOKEN_TRANSFER: case LoadGenMode::MIXED_PREGEN_SOROSWAP_SWAP: @@ -1931,8 +1903,7 @@ GeneratedLoadConfig::isSoroban() const mode == LoadGenMode::SOROBAN_UPLOAD || mode == LoadGenMode::SOROBAN_UPGRADE_SETUP || mode == LoadGenMode::SOROBAN_CREATE_UPGRADE || - mode == LoadGenMode::MIXED_CLASSIC_SOROBAN || - mode == LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD; + mode == LoadGenMode::MIXED_CLASSIC_SOROBAN; } bool @@ -1949,16 +1920,14 @@ GeneratedLoadConfig::isLoad() const mode == LoadGenMode::SOROBAN_INVOKE || mode == LoadGenMode::SOROBAN_CREATE_UPGRADE || mode == LoadGenMode::MIXED_CLASSIC_SOROBAN || - mode == LoadGenMode::PAY_PREGENERATED || - mode == LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD || modeMixesPregen(); + mode == LoadGenMode::PAY_PREGENERATED || modeMixesPregen(); } bool GeneratedLoadConfig::modeInvokes() const { return mode == LoadGenMode::SOROBAN_INVOKE || - mode == LoadGenMode::MIXED_CLASSIC_SOROBAN || - mode == LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD; + mode == LoadGenMode::MIXED_CLASSIC_SOROBAN; } bool diff --git a/src/simulation/LoadGenerator.h b/src/simulation/LoadGenerator.h index 8801274efb..74eae0195c 100644 --- a/src/simulation/LoadGenerator.h +++ b/src/simulation/LoadGenerator.h @@ -45,8 +45,6 @@ enum class LoadGenMode MIXED_CLASSIC_SOROBAN, // Submit pre-generated payment transactions from an XDR file PAY_PREGENERATED, - // Submit the same type of invoke transaction as ApplyLoad - SOROBAN_INVOKE_APPLY_LOAD, // Overlay-only modes: pre-generated classic payments + a soroban // transaction type of choice, each with its own TPS. No on-ledger setup // is required; soroban contract keys are synthesized in memory. Apply diff --git a/src/simulation/TxGenerator.cpp b/src/simulation/TxGenerator.cpp index 5f2dba47fe..d1e8f97eb1 100644 --- a/src/simulation/TxGenerator.cpp +++ b/src/simulation/TxGenerator.cpp @@ -372,8 +372,9 @@ increaseOpSize(Operation& op, uint32_t increaseUpToBytes) auth.rootInvocation.function.type( SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN); SCVal val(SCV_BYTES); + auth.rootInvocation.function.contractFn().args = {val}; - auto const overheadBytes = xdr::xdr_size(auth) + xdr::xdr_size(val); + auto const overheadBytes = xdr::xdr_size(auth); if (overheadBytes > increaseUpToBytes) { increaseUpToBytes = 0; @@ -552,7 +553,7 @@ TxGenerator::invokeSorobanLoadTransaction( std::pair TxGenerator::invokeSorobanLoadTransactionV2( uint32_t ledgerNum, uint64_t accountId, ContractInstance const& instance, - uint64_t dataEntryCount, size_t dataEntrySize, + ApplyLoadTxProfile const& txProfile, uint64_t dataEntryCount, std::optional maxGeneratedFeeRate) { auto const& appCfg = mApp.getConfig(); @@ -560,10 +561,9 @@ TxGenerator::invokeSorobanLoadTransactionV2( // The estimates below are fairly tight as they depend on linear // functions (maybe with a small constant factor as well). uint32_t const baseInstructionCount = 737'119; - uint32_t const baselineTxSizeBytes = 256; + uint32_t const baselineTxSizeBytes = 328; uint32_t const eventSize = TxGenerator::SOROBAN_LOAD_V2_EVENT_SIZE_BYTES; uint32_t const instructionsPerGuestCycle = 40; - uint32_t const instructionsPerHostCycle = 4'875; uint32_t const instructionsPerAuthByte = 35; uint32_t const instructionsPerEvent = 8'500; @@ -575,14 +575,10 @@ TxGenerator::invokeSorobanLoadTransactionV2( uint32_t archiveEntriesToRestore = 0; if (mPrePopulatedArchivedEntries != 0) { - archiveEntriesToRestore = sampleDiscrete( - appCfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES, - appCfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION, 0u); + archiveEntriesToRestore = txProfile.diskReadEntries; } - uint32_t rwEntries = - sampleDiscrete(appCfg.APPLY_LOAD_NUM_RW_ENTRIES, - appCfg.APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION, 0u); + uint32_t rwEntries = txProfile.rwEntries; // Subtract the archive entries from rwEntries since restoration counts as a // write @@ -641,26 +637,24 @@ TxGenerator::invokeSorobanLoadTransactionV2( } } - uint32_t txOverheadBytes = baselineTxSizeBytes + xdr::xdr_size(resources); - uint32_t desiredTxBytes = - sampleDiscrete(appCfg.APPLY_LOAD_TX_SIZE_BYTES, - appCfg.APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION, 0u); + uint32_t txOverheadBytes = baselineTxSizeBytes + xdr::xdr_size(resources) + + 4 * archivedIndexes.size(); + uint32_t desiredTxBytes = txProfile.txSizeBytes; uint32_t paddingBytes = txOverheadBytes > desiredTxBytes ? 0 : desiredTxBytes - txOverheadBytes; uint32_t entriesWriteSize = - dataEntrySize * (rwEntries + archiveEntriesToRestore); + txProfile.dataEntrySizeBytes * (rwEntries + archiveEntriesToRestore); uint32_t eventCount = sampleDiscrete(appCfg.APPLY_LOAD_EVENT_COUNT, appCfg.APPLY_LOAD_EVENT_COUNT_DISTRIBUTION, 0u); // Pick random number of cycles between bounds - uint32_t targetInstructions = - sampleDiscrete(appCfg.APPLY_LOAD_INSTRUCTIONS, - appCfg.APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION, 0u); + uint32_t targetInstructions = txProfile.instructions; resources.instructions = targetInstructions; resources.writeBytes = entriesWriteSize; - resources.diskReadBytes = dataEntrySize * archiveEntriesToRestore; + resources.diskReadBytes = + txProfile.dataEntrySizeBytes * archiveEntriesToRestore; auto numEntries = (rwEntries + archiveEntriesToRestore + instance.readOnlyKeys.size()); @@ -712,7 +706,14 @@ TxGenerator::invokeSorobanLoadTransactionV2( ihf.invokeContract().args = {makeU32(guestCycles), makeU32(hostCycles), makeU32(eventCount)}; - increaseOpSize(op, paddingBytes); + SorobanAuthorizationEntry auth; + auth.credentials.type(SOROBAN_CREDENTIALS_SOURCE_ACCOUNT); + auth.rootInvocation.function.type( + SOROBAN_AUTHORIZED_FUNCTION_TYPE_CONTRACT_FN); + SCVal val(SCV_BYTES); + val.bytes().resize(paddingBytes); + auth.rootInvocation.function.contractFn().args = {val}; + op.body.invokeHostFunctionOp().auth = {auth}; auto resourceFee = sorobanResourceFee(mApp, resources, txOverheadBytes + paddingBytes, @@ -733,6 +734,12 @@ TxGenerator::invokeSorobanLoadTransactionV2( resourceFee, std::nullopt, std::nullopt, archivedIndexes.empty() ? std::nullopt : std::make_optional(archivedIndexes)); + auto txSize = xdr::xdr_size(tx->getEnvelope()); + if (txSize != txProfile.txSizeBytes) + { + CLOG_WARNING(Perf, "Tx size is different than desired: {} vs {}", + txSize, txProfile.txSizeBytes); + } return std::make_pair(account, tx); } diff --git a/src/simulation/TxGenerator.h b/src/simulation/TxGenerator.h index 76c0c8a88b..ebed981e03 100644 --- a/src/simulation/TxGenerator.h +++ b/src/simulation/TxGenerator.h @@ -101,6 +101,15 @@ struct SorobanUpgradeConfig std::optional freezeBypassTxsDelta{}; }; +struct ApplyLoadTxProfile +{ + uint32_t instructions = 0; + uint32_t txSizeBytes = 0; + uint32_t diskReadEntries = 0; + uint32_t rwEntries = 0; + uint32_t dataEntrySizeBytes = 0; +}; + class TxGenerator { public: @@ -215,8 +224,8 @@ class TxGenerator std::pair invokeSorobanLoadTransactionV2(uint32_t ledgerNum, uint64_t accountId, ContractInstance const& instance, + ApplyLoadTxProfile const& txProfile, uint64_t dataEntryCount, - size_t dataEntrySize, std::optional maxGeneratedFeeRate); std::pair invokeSACPayment(uint32_t ledgerNum, uint64_t fromAccountId, diff --git a/src/simulation/test/LoadGeneratorTests.cpp b/src/simulation/test/LoadGeneratorTests.cpp index dc1fee9760..560186b2f1 100644 --- a/src/simulation/test/LoadGeneratorTests.cpp +++ b/src/simulation/test/LoadGeneratorTests.cpp @@ -29,10 +29,6 @@ TEST_CASE("loadgen in overlay-only mode", "[loadgen]") Simulation::pointer simulation = Topologies::pair(Simulation::OVER_LOOPBACK, networkID, [&](int i) { auto cfg = getTestConfig(i); - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES = {10}; - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = {100}; - cfg.APPLY_LOAD_NUM_RW_ENTRIES = {5}; - cfg.APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = {100}; cfg.LOADGEN_INSTRUCTIONS_FOR_TESTING = {10'000'000, 50'000'000}; cfg.LOADGEN_INSTRUCTIONS_DISTRIBUTION_FOR_TESTING = {5, 1}; cfg.ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING = true; @@ -92,13 +88,6 @@ TEST_CASE("loadgen in overlay-only mode", "[loadgen]") app.getLoadGenerator().generateLoad(GeneratedLoadConfig::txLoad( LoadGenMode::PAY, nAccounts, nTxs, /* txRate */ 1)); } - SECTION("invoke realistic") - { - // Simulate realistic invoke transactions - app.getLoadGenerator().generateLoad( - GeneratedLoadConfig::txLoad(LoadGenMode::SOROBAN_INVOKE_APPLY_LOAD, - nAccounts, nTxs, /* txRate */ 1)); - } simulation->crankUntil( [&]() { return app.getMetrics() @@ -757,7 +746,7 @@ TEST_CASE("generate soroban load", "[loadgen][soroban]") }, simulation); auto const numInstances = nAccounts; - auto const numSorobanTxs = 150; + auto const numSorobanTxs = 500; numTxsBefore = getSuccessfulTxCount(); @@ -1005,8 +994,6 @@ TEST_CASE("apply load", "[loadgen][applyload][acceptance]") cfg.APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 100; - cfg.APPLY_LOAD_DATA_ENTRY_SIZE = 1000; - // BL generation parameters cfg.APPLY_LOAD_BL_SIMULATED_LEDGERS = 10000; cfg.APPLY_LOAD_BL_WRITE_FREQUENCY = 1000; @@ -1014,32 +1001,19 @@ TEST_CASE("apply load", "[loadgen][applyload][acceptance]") cfg.APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300; cfg.APPLY_LOAD_BL_LAST_BATCH_SIZE = 100; - // Load generation parameters - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES = {0, 1, 2}; - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = {3, 2, 1}; - - cfg.APPLY_LOAD_NUM_RW_ENTRIES = {1, 5, 10}; - cfg.APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = {1, 1, 1}; - cfg.APPLY_LOAD_EVENT_COUNT = {100}; cfg.APPLY_LOAD_EVENT_COUNT_DISTRIBUTION = {1}; - cfg.APPLY_LOAD_TX_SIZE_BYTES = {1'000, 2'000, 5'000}; - cfg.APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = {3, 2, 1}; - - cfg.APPLY_LOAD_INSTRUCTIONS = {10'000'000, 50'000'000}; - cfg.APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = {5, 1}; - // Ledger and transaction limits cfg.APPLY_LOAD_LEDGER_MAX_INSTRUCTIONS = 500'000'000; cfg.APPLY_LOAD_TX_MAX_INSTRUCTIONS = 100'000'000; cfg.APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 2; - cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_LEDGER_ENTRIES = 2000; - cfg.APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 100; + cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_LEDGER_ENTRIES = 200; + cfg.APPLY_LOAD_TX_MAX_DISK_READ_LEDGER_ENTRIES = 10; cfg.APPLY_LOAD_TX_MAX_FOOTPRINT_SIZE = 100; - cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 50'000'000; + cfg.APPLY_LOAD_LEDGER_MAX_DISK_READ_BYTES = 1'000'000; cfg.APPLY_LOAD_TX_MAX_DISK_READ_BYTES = 200'000; cfg.APPLY_LOAD_LEDGER_MAX_WRITE_LEDGER_ENTRIES = 1250; @@ -1064,9 +1038,7 @@ TEST_CASE("apply load", "[loadgen][applyload][acceptance]") ApplyLoad al(*app); // Sample a few indices to verify hot archive is properly initialized - uint32_t expectedArchivedEntries = - ApplyLoad::calculateRequiredHotArchiveEntries( - ApplyLoadMode::LIMIT_BASED, cfg); + uint32_t expectedArchivedEntries = al.getTotalHotArchiveEntries(); std::vector sampleIndices = {0, expectedArchivedEntries / 2, expectedArchivedEntries - 1}; std::set sampleKeys; @@ -1086,70 +1058,6 @@ TEST_CASE("apply load", "[loadgen][applyload][acceptance]") REQUIRE(1.0 - al.successRate() < std::numeric_limits::epsilon()); } -TEST_CASE("apply load find max limits for model tx", - "[loadgen][applyload][acceptance]") -{ - auto cfg = getTestConfig(); - cfg.APPLY_LOAD_MODE = ApplyLoadMode::FIND_LIMITS_FOR_MODEL_TX; - cfg.TESTING_UPGRADE_MAX_TX_SET_SIZE = 1000; - cfg.USE_CONFIG_FOR_GENESIS = true; - cfg.LEDGER_PROTOCOL_VERSION = Config::CURRENT_LEDGER_PROTOCOL_VERSION; - cfg.MANUAL_CLOSE = true; - cfg.ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING = true; - cfg.GENESIS_TEST_ACCOUNT_COUNT = 10000; - - // Also generate that many classic simple payments. - cfg.APPLY_LOAD_CLASSIC_TXS_PER_LEDGER = 100; - - // Close 30 ledgers per iteration. - cfg.APPLY_LOAD_NUM_LEDGERS = 30; - // The target close time is 500ms. - cfg.APPLY_LOAD_TARGET_CLOSE_TIME_MS = 500; - - // Size of each data entry to be used in the test. - cfg.APPLY_LOAD_DATA_ENTRY_SIZE = 100; - - // BL generation parameters - cfg.APPLY_LOAD_BL_SIMULATED_LEDGERS = 1000; - cfg.APPLY_LOAD_BL_WRITE_FREQUENCY = 1000; - cfg.APPLY_LOAD_BL_BATCH_SIZE = 1000; - cfg.APPLY_LOAD_BL_LAST_BATCH_LEDGERS = 300; - cfg.APPLY_LOAD_BL_LAST_BATCH_SIZE = 100; - - // Load generation parameters - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES = {1}; - cfg.APPLY_LOAD_NUM_DISK_READ_ENTRIES_DISTRIBUTION = {1}; - - cfg.APPLY_LOAD_NUM_RW_ENTRIES = {4}; - cfg.APPLY_LOAD_NUM_RW_ENTRIES_DISTRIBUTION = {1}; - - cfg.APPLY_LOAD_EVENT_COUNT = {2}; - cfg.APPLY_LOAD_EVENT_COUNT_DISTRIBUTION = {1}; - - cfg.APPLY_LOAD_TX_SIZE_BYTES = {1000}; - cfg.APPLY_LOAD_TX_SIZE_BYTES_DISTRIBUTION = {1}; - - cfg.APPLY_LOAD_INSTRUCTIONS = {2'000'000}; - cfg.APPLY_LOAD_INSTRUCTIONS_DISTRIBUTION = {1}; - - // Only a few ledger limits need to be specified, the rest will be found by - // the benchmark itself. - // Number of soroban txs per ledger is the upper bound of the binary - // search for the number of the model txs to include in each ledger. - cfg.APPLY_LOAD_MAX_SOROBAN_TX_COUNT = 1000; - // Use 2 clusters/threads. - cfg.APPLY_LOAD_LEDGER_MAX_DEPENDENT_TX_CLUSTERS = 2; - - VirtualClock clock(VirtualClock::REAL_TIME); - auto app = createTestApplication(clock, cfg); - - ApplyLoad al(*app); - - al.execute(); - - REQUIRE(1.0 - al.successRate() < std::numeric_limits::epsilon()); -} - TEST_CASE("apply load find max SAC TPS", "[loadgen][applyload][soroban][acceptance]") {