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

Make transaction generator a configurable option to TransactionGeneratorsLauncher. #1579

Merged
merged 5 commits into from
Aug 31, 2023
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
2 changes: 1 addition & 1 deletion tests/PerformanceHarness/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The `PerformanceTest`'s main goal is to measure current peak performance metrics

The `PerformanceTestBasic` test performs a single basic performance test that targets a configurable TPS target and, if successful, reports statistics on performance metrics measured during the test. It configures and launches a blockchain test environment, creates wallets and accounts for testing, and configures and launches transaction generators for creating specific transaction load in the ecosystem. Finally it analyzes the performance of the system under the configuration through log analysis and chain queries and produces a [Performance Test Basic Report](#performance-test-basic-report).

The `launch_generators.py` support script provides a means to easily calculate and spawn the number of transaction generator instances to generate a given target TPS, distributing generation load between the instances in a fair manner such that the aggregate load meets the requested test load.
The `TransactionGeneratorsLauncher` provides a means to easily calculate and spawn the number of transaction generator instances to generate a given target TPS, distributing generation load between the instances in a fair manner such that the aggregate load meets the requested test load.

The `log_reader.py` support script is used primarily to analyze `nodeos` log files to glean information about generated blocks and transactions within those blocks after a test has concluded. This information is used to produce the performance test report.

Expand Down
8 changes: 6 additions & 2 deletions tests/PerformanceHarness/performance_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ class PtConfig:
userTrxDataFile: Path=None
endpointMode: str="p2p"
opModeCmd: str=""
trxGenerator: Path=Path(".")


def __post_init__(self):
self.opModeDesc = "Block Producer Operational Mode" if self.opModeCmd == "testBpOpMode" else "API Node Operational Mode" if self.opModeCmd == "testApiOpMode" else "Undefined Operational Mode"
Expand Down Expand Up @@ -112,7 +114,8 @@ def performPtbBinarySearch(self, clusterConfig: PerformanceTestBasic.ClusterConf
scenarioResult = PerformanceTest.PerfTestSearchIndivResult(success=False, searchTarget=binSearchTarget, searchFloor=floor, searchCeiling=ceiling)
ptbConfig = PerformanceTestBasic.PtbConfig(targetTps=binSearchTarget, testTrxGenDurationSec=self.ptConfig.testDurationSec, tpsLimitPerGenerator=self.ptConfig.tpsLimitPerGenerator,
numAddlBlocksToPrune=self.ptConfig.numAddlBlocksToPrune, logDirRoot=logDirRoot, delReport=delReport,
quiet=quiet, userTrxDataFile=self.ptConfig.userTrxDataFile, endpointMode=self.ptConfig.endpointMode)
quiet=quiet, userTrxDataFile=self.ptConfig.userTrxDataFile, endpointMode=self.ptConfig.endpointMode,
trxGenerator=self.ptConfig.trxGenerator)

myTest = PerformanceTestBasic(testHelperConfig=self.testHelperConfig, clusterConfig=clusterConfig, ptbConfig=ptbConfig, testNamePath=os.path.basename(sys.argv[0]).rsplit('.',maxsplit=1)[0])
myTest.runTest()
Expand Down Expand Up @@ -154,7 +157,8 @@ def performPtbReverseLinearSearch(self, tpsInitial: int) -> TpsTestResult.PerfTe
scenarioResult = PerformanceTest.PerfTestSearchIndivResult(success=False, searchTarget=searchTarget, searchFloor=absFloor, searchCeiling=absCeiling)
ptbConfig = PerformanceTestBasic.PtbConfig(targetTps=searchTarget, testTrxGenDurationSec=self.ptConfig.testDurationSec, tpsLimitPerGenerator=self.ptConfig.tpsLimitPerGenerator,
numAddlBlocksToPrune=self.ptConfig.numAddlBlocksToPrune, logDirRoot=self.loggingConfig.ptbLogsDirPath, delReport=self.ptConfig.delReport,
quiet=self.ptConfig.quiet, delPerfLogs=self.ptConfig.delPerfLogs, userTrxDataFile=self.ptConfig.userTrxDataFile, endpointMode=self.ptConfig.endpointMode)
quiet=self.ptConfig.quiet, delPerfLogs=self.ptConfig.delPerfLogs, userTrxDataFile=self.ptConfig.userTrxDataFile, endpointMode=self.ptConfig.endpointMode,
trxGenerator=self.ptConfig.trxGenerator)

myTest = PerformanceTestBasic(testHelperConfig=self.testHelperConfig, clusterConfig=self.clusterConfig, ptbConfig=ptbConfig, testNamePath=os.path.basename(sys.argv[0]).rsplit('.',maxsplit=1)[0])
myTest.runTest()
Expand Down
5 changes: 3 additions & 2 deletions tests/PerformanceHarness/performance_test_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ class PtbConfig:
userTrxDataFile: Path=None
endpointMode: str="p2p"
apiEndpoint: str=None

trxGenerator: Path=Path(".")

def __post_init__(self):
self.expectedTransactionsSent = self.testTrxGenDurationSec * self.targetTps
Expand Down Expand Up @@ -454,7 +454,7 @@ def configureConnections():
self.data.startBlock = self.waitForEmptyBlocks(self.validationNode, self.emptyBlockGoal)
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=self.ptbConfig.targetTps, tpsLimitPerGenerator=self.ptbConfig.tpsLimitPerGenerator, connectionPairList=self.connectionPairList)

self.cluster.trxGenLauncher = TransactionGeneratorsLauncher(chainId=chainId, lastIrreversibleBlockId=lib_id, contractOwnerAccount=self.clusterConfig.specifiedContract.account.name,
self.cluster.trxGenLauncher = TransactionGeneratorsLauncher(trxGenerator=self.ptbConfig.trxGenerator, chainId=chainId, lastIrreversibleBlockId=lib_id, contractOwnerAccount=self.clusterConfig.specifiedContract.account.name,
accts=','.join(map(str, self.accountNames)), privateKeys=','.join(map(str, self.accountPrivKeys)),
trxGenDurationSec=self.ptbConfig.testTrxGenDurationSec, logDir=self.trxGenLogDirPath,
abiFile=abiFile, actionsData=actionsDataJson, actionsAuths=actionsAuthsJson,
Expand Down Expand Up @@ -722,6 +722,7 @@ def _createBaseArgumentParser(defEndpointApiDef: str, defProdNodeCnt: int, defVa
block log file is removed after startup.", default=None)
ptbBaseParserGroup.add_argument("--http-threads", type=int, help=argparse.SUPPRESS if suppressHelp else "Number of worker threads in http thread pool", default=2)
ptbBaseParserGroup.add_argument("--chain-state-db-size-mb", type=int, help=argparse.SUPPRESS if suppressHelp else "Maximum size (in MiB) of the chain state database", default=25600)
ptbBaseParserGroup.add_argument("--trx-generator", type=str, help=argparse.SUPPRESS if suppressHelp else "Transaction Generator executable", default="./tests/trx_generator/trx_generator")

return ptbBaseParser

Expand Down
6 changes: 4 additions & 2 deletions tests/PerformanceHarnessScenarioRunner.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def main():
delPerfLogs=args.del_perf_logs,
printMissingTransactions=args.print_missing_transactions,
userTrxDataFile=Path(args.user_trx_data_file) if args.user_trx_data_file is not None else None,
endpointMode=args.endpoint_mode)
endpointMode=args.endpoint_mode,
trxGenerator=args.trx_generator)
Utils.Print(f"testNamePath: {PurePath(PurePath(__file__).name).stem}")
myTest = performance_test_basic.PerformanceTestBasic(testHelperConfig=testHelperConfig, clusterConfig=testClusterConfig, ptbConfig=ptbConfig, testNamePath=f"{PurePath(PurePath(__file__).name).stem}")
elif args.scenario_type_sub_cmd == "findMax":
Expand All @@ -85,7 +86,8 @@ def main():
calcNetThreads=args.calc_net_threads,
userTrxDataFile=Path(args.user_trx_data_file) if args.user_trx_data_file is not None else None,
endpointMode=args.endpoint_mode,
opModeCmd=args.op_mode_sub_cmd)
opModeCmd=args.op_mode_sub_cmd,
trxGenerator=args.trx_generator)

myTest = performance_test.PerformanceTest(testHelperConfig=testHelperConfig, clusterConfig=testClusterConfig, ptConfig=ptConfig)
else:
Expand Down
2 changes: 1 addition & 1 deletion tests/TestHarness/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ configure_file(queries.py . COPYONLY)
configure_file(transactions.py . COPYONLY)
configure_file(libc.py . COPYONLY)
configure_file(interfaces.py . COPYONLY)
configure_file(launch_transaction_generators.py . COPYONLY)
configure_file(TransactionGeneratorsLauncher.py . COPYONLY)
configure_file(logging.py . COPYONLY)
configure_file(depresolver.py . COPYONLY)
configure_file(launcher.py . COPYONLY)
Expand Down
7 changes: 4 additions & 3 deletions tests/TestHarness/Cluster.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from .Node import BlockType
from .Node import Node
from .WalletMgr import WalletMgr
from .launch_transaction_generators import TransactionGeneratorsLauncher, TpsTrxGensConfig
from .TransactionGeneratorsLauncher import TransactionGeneratorsLauncher, TpsTrxGensConfig
from .launcher import cluster_generator
try:
from .libc import unshare, CLONE_NEWNET
Expand Down Expand Up @@ -1554,7 +1554,8 @@ def stripValues(lowestMaxes,greaterThan):

def launchTrxGenerators(self, contractOwnerAcctName: str, acctNamesList: list, acctPrivKeysList: list,
nodeId: int=0, tpsPerGenerator: int=10, numGenerators: int=1, durationSec: int=60,
waitToComplete:bool=False, abiFile=None, actionsData=None, actionsAuths=None):
waitToComplete:bool=False, abiFile=None, actionsData=None, actionsAuths=None,
trxGenerator=Path("./tests/trx_generator/trx_generator")):
Utils.Print("Configure txn generators")
node=self.getNode(nodeId)
info = node.getInfo()
Expand All @@ -1567,7 +1568,7 @@ def launchTrxGenerators(self, contractOwnerAcctName: str, acctNamesList: list, a
self.preExistingFirstTrxFiles = glob.glob(f"{Utils.DataDir}/first_trx_*.txt")
connectionPairList = [f"{self.host}:{self.getNodeP2pPort(nodeId)}"]
tpsTrxGensConfig = TpsTrxGensConfig(targetTps=targetTps, tpsLimitPerGenerator=tpsLimitPerGenerator, connectionPairList=connectionPairList)
self.trxGenLauncher = TransactionGeneratorsLauncher(chainId=chainId, lastIrreversibleBlockId=lib_id,
self.trxGenLauncher = TransactionGeneratorsLauncher(trxGenerator=trxGenerator, chainId=chainId, lastIrreversibleBlockId=lib_id,
contractOwnerAccount=contractOwnerAcctName, accts=','.join(map(str, acctNamesList)),
privateKeys=','.join(map(str, acctPrivKeysList)), trxGenDurationSec=durationSec, logDir=Utils.DataDir,
abiFile=abiFile, actionsData=actionsData, actionsAuths=actionsAuths, tpsTrxGensConfig=tpsTrxGensConfig,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ def __init__(self, targetTps: int, tpsLimitPerGenerator: int, connectionPairList

class TransactionGeneratorsLauncher:

def __init__(self, chainId: int, lastIrreversibleBlockId: int, contractOwnerAccount: str, accts: str, privateKeys: str, trxGenDurationSec: int, logDir: str,
def __init__(self, trxGenerator: Path, chainId: int, lastIrreversibleBlockId: int, contractOwnerAccount: str, accts: str, privateKeys: str, trxGenDurationSec: int, logDir: str,
abiFile: Path, actionsData, actionsAuths, tpsTrxGensConfig: TpsTrxGensConfig, endpointMode: str, apiEndpoint: str=None):
self.trxGenerator = trxGenerator
self.chainId = chainId
self.lastIrreversibleBlockId = lastIrreversibleBlockId
self.contractOwnerAccount = contractOwnerAccount
Expand All @@ -59,7 +60,8 @@ def launch(self, waitToComplete=True):
for id, targetTps in enumerate(self.tpsTrxGensConfig.targetTpsPerGenList):
connectionPair = self.tpsTrxGensConfig.connectionPairList[connectionPairIter].rsplit(":")
popenStringList = [
'./tests/trx_generator/trx_generator',
# './tests/trx_generator/trx_generator',
f'{self.trxGenerator}',
'--generator-id', f'{id}',
'--chain-id', f'{self.chainId}',
'--last-irreversible-block-id', f'{self.lastIrreversibleBlockId}',
Expand All @@ -80,7 +82,7 @@ def launch(self, waitToComplete=True):
popenStringList.extend(['--api-endpoint', f'{self.apiEndpoint}'])

if Utils.Debug:
Print(f"Running trx_generator: {' '.join(popenStringList)}")
Print(f"Running transaction generator {self.trxGenerator} : {' '.join(popenStringList)}")
self.subprocess_ret_codes.append(subprocess.Popen(popenStringList))
connectionPairIter = (connectionPairIter + 1) % len(self.tpsTrxGensConfig.connectionPairList)
exitCodes=None
Expand All @@ -97,6 +99,7 @@ def killAll(self):
def parseArgs():
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('-?', '--help', action='help', default=argparse.SUPPRESS, help=argparse._('show this help message and exit'))
parser.add_argument("trx_generator", type=str, help="The path to the transaction generator binary to excecute")
parser.add_argument("chain_id", type=str, help="Chain ID")
parser.add_argument("last_irreversible_block_id", type=str, help="Last irreversible block ID")
parser.add_argument("contract_owner_account", type=str, help="Cluster contract owner account name")
Expand All @@ -119,23 +122,3 @@ def parseArgs():

args = parser.parse_args()
return args

def main():
args = parseArgs()
connectionPairList = sub('[\s+]', '', args.connection_pair_list)
connectionPairList = connectionPairList.rsplit(',')

trxGenLauncher = TransactionGeneratorsLauncher(chainId=args.chain_id, lastIrreversibleBlockId=args.last_irreversible_block_id,
contractOwnerAccount=args.contract_owner_account, accts=args.accounts,
privateKeys=args.priv_keys, trxGenDurationSec=args.trx_gen_duration, logDir=args.log_dir,
abiFile=args.abi_file, actionsData=args.actions_data, actionsAuths=args.actions_auths,
tpsTrxGensConfig=TpsTrxGensConfig(targetTps=args.target_tps, tpsLimitPerGenerator=args.tps_limit_per_generator,
connectionPairList=connectionPairList),
endpointMode=args.endpoint_mode, apiEndpoint=args.api_endpoint)


exit_codes = trxGenLauncher.launch()
exit(exit_codes)

if __name__ == '__main__':
main()
4 changes: 2 additions & 2 deletions tests/TestHarness/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__all__ = ['Node', 'Cluster', 'WalletMgr', 'launcher', 'logging', 'depresolver', 'testUtils', 'TestHelper', 'queries', 'transactions', 'accounts', 'launch_transaction_generators', 'TransactionGeneratorsLauncher', 'TpsTrxGensConfig', 'core_symbol']
__all__ = ['Node', 'Cluster', 'WalletMgr', 'launcher', 'logging', 'depresolver', 'testUtils', 'TestHelper', 'queries', 'transactions', 'accounts', 'TransactionGeneratorsLauncher', 'TpsTrxGensConfig', 'core_symbol']

from .Cluster import Cluster
from .Node import Node
Expand All @@ -9,5 +9,5 @@
from .testUtils import Utils
from .Node import ReturnType
from .TestHelper import TestHelper
from .launch_transaction_generators import TransactionGeneratorsLauncher, TpsTrxGensConfig
from .TransactionGeneratorsLauncher import TransactionGeneratorsLauncher, TpsTrxGensConfig
from .core_symbol import CORE_SYMBOL