Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply time benchmarking #4402

Merged
merged 6 commits into from
Sep 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/software/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,22 @@ Common options can be placed at any place in the command line.
## Command line options
Command options can only by placed after command.

* **apply-load**: Applies Soroban transactions by repeatedly generating transactions and closing
them directly through the LedgerManager. The parameters specified below configure the network limits, and
they're all required - **--ledger-max-instructions N**, **--ledger-max-read-entries N**, **--ledger-max-write-entries N**, **--ledger-max-read-byte N**, **--ledger-max-write-bytes N**, **--ledger-max-tx-size N**, **--ledger-max-tx-count N**. This command will generate enough transactions to fill up a synthetic transaction queue (it's just a list of transactions with the same limits as the real queue), and then create a transaction set off of that to
apply.

* At the moment, the Soroban transactions are generated using some of the same config parameters as the **generateload** command. Specifically,
`ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=true`,
`LOADGEN_NUM_DATA_ENTRIES_FOR_TESTING`,
`LOADGEN_NUM_DATA_ENTRIES_DISTRIBUTION_FOR_TESTING`,
`LOADGEN_IO_KILOBYTES_FOR_TESTING`,
`LOADGEN_IO_KILOBYTES_DISTRIBUTION_FOR_TESTING`,
`LOADGEN_TX_SIZE_BYTES_FOR_TESTING`,
`LOADGEN_TX_SIZE_BYTES_DISTRIBUTION_FOR_TESTING`,
`LOADGEN_INSTRUCTIONS_FOR_TESTING`, and
`LOADGEN_INSTRUCTIONS_DISTRIBUTION_FOR_TESTING`.

* **catchup <DESTINATION-LEDGER/LEDGER-COUNT>**: Perform catchup from history
archives without connecting to network. For new instances (with empty history
tables - only ledger 1 present in the database) it will respect LEDGER-COUNT
Expand Down
2 changes: 1 addition & 1 deletion docs/stellar-core_example.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ MANUAL_CLOSE=false

# ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING (true or false) defaults to false
# Enables synthetic load generation on demand.
# The load is triggered by the `generateload` runtime command.
sisuresh marked this conversation as resolved.
Show resolved Hide resolved
# The load is triggered by the `generateload` runtime command or the `apply-load` command line command.
# This option only exists for stress-testing and should not be enabled in
# production networks.
ARTIFICIALLY_GENERATE_LOAD_FOR_TESTING=false
Expand Down
1 change: 0 additions & 1 deletion src/herder/HerderImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ constexpr uint32 const CLOSE_TIME_DRIFT_SECONDS_THRESHOLD = 10;
constexpr uint32 const TRANSACTION_QUEUE_TIMEOUT_LEDGERS = 4;
constexpr uint32 const TRANSACTION_QUEUE_BAN_LEDGERS = 10;
constexpr uint32 const TRANSACTION_QUEUE_SIZE_MULTIPLIER = 2;
constexpr uint32 const SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER = 2;

std::unique_ptr<Herder>
Herder::create(Application& app)
Expand Down
2 changes: 2 additions & 0 deletions src/herder/HerderImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Timer;

namespace stellar
{
constexpr uint32 const SOROBAN_TRANSACTION_QUEUE_SIZE_MULTIPLIER = 2;

class Application;
class LedgerManager;
class HerderSCPDriver;
Expand Down
3 changes: 2 additions & 1 deletion src/main/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,8 @@ CommandHandler::generateLoad(std::string const& params, std::string& retStr)
if (cfg.mode == LoadGenMode::SOROBAN_CREATE_UPGRADE)
{
auto configUpgradeKey =
mApp.getLoadGenerator().getConfigUpgradeSetKey(cfg);
mApp.getLoadGenerator().getConfigUpgradeSetKey(
cfg.getSorobanUpgradeConfig());
auto configUpgradeKeyStr = stellar::decoder::encode_b64(
xdr::xdr_to_opaque(configUpgradeKey));
res["config_upgrade_set_key"] = configUpgradeKeyStr;
Expand Down
164 changes: 164 additions & 0 deletions src/main/CommandLine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@
#include "main/SettingsUpgradeUtils.h"
#include "main/StellarCoreVersion.h"
#include "main/dumpxdr.h"
#include "medida/metrics_registry.h"
#include "overlay/OverlayManager.h"
#include "rust/RustBridge.h"
#include "scp/QuorumSetUtils.h"
#include "simulation/ApplyLoad.h"
#include "transactions/TransactionUtils.h"
#include "util/Logging.h"
#include "util/types.h"
Expand Down Expand Up @@ -1799,6 +1801,167 @@ runGenFuzz(CommandLineArgs const& args)
return 0;
});
}

int
runApplyLoad(CommandLineArgs const& args)
{
CommandLine::ConfigOption configOption;

uint64_t ledgerMaxInstructions = 0;
uint64_t ledgerMaxReadLedgerEntries = 0;
uint64_t ledgerMaxReadBytes = 0;
uint64_t ledgerMaxWriteLedgerEntries = 0;
uint64_t ledgerMaxWriteBytes = 0;
uint64_t ledgerMaxTxCount = 0;
uint64_t ledgerMaxTransactionsSizeBytes = 0;

ParserWithValidation ledgerMaxInstructionsParser{
clara::Opt(ledgerMaxInstructions,
"LedgerMaxInstructions")["--ledger-max-instructions"]
.required(),
[&] {
return ledgerMaxInstructions > 0
? ""
: "ledgerMaxInstructions must be > 0";
}};

ParserWithValidation ledgerMaxReadLedgerEntriesParser{
clara::Opt(ledgerMaxReadLedgerEntries,
"LedgerMaxReadLedgerEntries")["--ledger-max-read-entries"]
.required(),
[&] {
return ledgerMaxReadLedgerEntries > 0
? ""
: "ledgerMaxReadLedgerEntries must be > 0";
}};

ParserWithValidation ledgerMaxReadBytesParser{
clara::Opt(ledgerMaxReadBytes,
"LedgerMaxReadBytes")["--ledger-max-read-bytes"]
.required(),
[&] {
return ledgerMaxReadBytes > 0 ? ""
: "ledgerMaxReadBytes must be > 0";
}};

ParserWithValidation ledgerMaxWriteLedgerEntriesParser{
clara::Opt(ledgerMaxWriteLedgerEntries,
"LedgerMaxWriteLedgerEntries")["--ledger-max-write-entries"]
.required(),
[&] {
return ledgerMaxWriteLedgerEntries > 0
? ""
: "ledgerMaxWriteLedgerEntries must be > 0";
}};

ParserWithValidation ledgerMaxWriteBytesParser{
clara::Opt(ledgerMaxWriteBytes,
"LedgerMaxWriteBytes")["--ledger-max-write-bytes"]
.required(),
[&] {
return ledgerMaxWriteBytes > 0 ? ""
: "ledgerMaxWriteBytes must be > 0";
}};

ParserWithValidation ledgerMaxTxCountParser{
clara::Opt(ledgerMaxTxCount,
"LedgerMaxTxCount")["--ledger-max-tx-count"]
.required(),
[&] {
return ledgerMaxTxCount > 0 ? "" : "ledgerMaxTxCount must be > 0";
}};

ParserWithValidation ledgerMaxTransactionsSizeBytesParser{
clara::Opt(ledgerMaxTransactionsSizeBytes,
"LedgerMaxTransactionsSizeBytes")["--ledger-max-tx-size"]
.required(),
[&] {
return ledgerMaxTransactionsSizeBytes > 0
? ""
: "ledgerMaxTransactionsSizeBytes must be > 0";
}};

return runWithHelp(
args,
{configurationParser(configOption), ledgerMaxInstructionsParser,
ledgerMaxReadLedgerEntriesParser, ledgerMaxReadBytesParser,
ledgerMaxWriteLedgerEntriesParser, ledgerMaxWriteBytesParser,
ledgerMaxTxCountParser, ledgerMaxTransactionsSizeBytesParser},
[&] {
auto config = configOption.getConfig();
config.RUN_STANDALONE = true;

VirtualClock clock(VirtualClock::REAL_TIME);
auto appPtr = Application::create(clock, config);

auto& app = *appPtr;
{
auto& lm = app.getLedgerManager();
app.start();

ApplyLoad al(app, ledgerMaxInstructions,
ledgerMaxReadLedgerEntries, ledgerMaxReadBytes,
ledgerMaxWriteLedgerEntries, ledgerMaxWriteBytes,
ledgerMaxTxCount, ledgerMaxTransactionsSizeBytes);

auto& ledgerClose =
app.getMetrics().NewTimer({"ledger", "ledger", "close"});
ledgerClose.Clear();

auto& cpuInsRatio = app.getMetrics().NewHistogram(
{"soroban", "host-fn-op",
"invoke-time-fsecs-cpu-insn-ratio"});
cpuInsRatio.Clear();

auto& cpuInsRatioExclVm = app.getMetrics().NewHistogram(
{"soroban", "host-fn-op",
"invoke-time-fsecs-cpu-insn-ratio-excl-vm"});
cpuInsRatioExclVm.Clear();

for (size_t i = 0; i < 20; ++i)
{
al.benchmark();
}

CLOG_INFO(Perf, "Max ledger close: {} milliseconds",
ledgerClose.max());
CLOG_INFO(Perf, "Min ledger close: {} milliseconds",
ledgerClose.min());
CLOG_INFO(Perf, "Mean ledger close: {} milliseconds",
sisuresh marked this conversation as resolved.
Show resolved Hide resolved
ledgerClose.mean());

CLOG_INFO(Perf, "Max CPU ins ratio: {}",
cpuInsRatio.max() / 1000000);
CLOG_INFO(Perf, "Mean CPU ins ratio: {}",
cpuInsRatio.mean() / 1000000);

CLOG_INFO(Perf, "Max CPU ins ratio excl VM: {}",
cpuInsRatioExclVm.max() / 1000000);
CLOG_INFO(Perf, "Mean CPU ins ratio excl VM: {}",
cpuInsRatioExclVm.mean() / 1000000);

CLOG_INFO(Perf, "Tx count utilization {}%",
al.getTxCountUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Instruction utilization {}%",
al.getInstructionUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Tx size utilization {}%",
al.getTxSizeUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Read bytes utilization {}%",
al.getReadByteUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Write bytes utilization {}%",
al.getWriteByteUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Read entry utilization {}%",
al.getReadEntryUtilization().mean() / 1000.0);
CLOG_INFO(Perf, "Write entry utilization {}%",
al.getWriteEntryUtilization().mean() / 1000.0);

CLOG_INFO(Perf, "Tx Success Rate: {:f}%",
al.successRate() * 100);
}

return 0;
});
}
#endif

int
Expand Down Expand Up @@ -1871,6 +2034,7 @@ handleCommandLine(int argc, char* const* argv)
{"fuzz", "run a single fuzz input and exit", runFuzz},
{"gen-fuzz", "generate a random fuzzer input file", runGenFuzz},
{"test", "execute test suite", runTest},
{"apply-load", "run apply time load test", runApplyLoad},
#endif
{"version", "print version information", runVersion}}};

Expand Down
Loading
Loading