Skip to content

Commit c0b13a5

Browse files
authored
feat(tools): add the stress test tool (#49)
1 parent fca0d04 commit c0b13a5

23 files changed

+2963
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ We also provide tools to facilitate the CI and testing process:
2626
- `root`: compute merkle root for tiny db. NOTE: large db may GC overhead
2727
limit exceeded.
2828
- `fork`: Modify the database of java-tron for shadow fork testing.
29+
- **Stress Test**: Execute the stress test and evaluate the performance of the `java-tron` fullnode.
30+
2931

3032
## Prerequisites
3133
Please ensure you have the latest versions of Docker and Docker Compose installed by downloading them from the official websites:
@@ -133,6 +135,7 @@ To start all available features, or you want more customized operations, navigat
133135
- **Tools**:
134136
- **Gradle Docker**: Automate Docker image builds and testing. Check the [gradle docker](./tools/docker/README.md) documentation.
135137
- **Toolkit**: Perform a set of database related operations. Follow the [Toolkit guidance](./tools/toolkit/README.md).
138+
- **Stress Test**: Execute the stress test. Follow the [stress test guidance](./tools/stress_test/README.md).
136139

137140
## Troubleshooting
138141
If you encounter any difficulties, please refer to the [Issue Work Flow](https://tronprotocol.github.io/documentation-en/developers/issue-workflow/#issue-work-flow), then raise an issue on [GitHub](https://github.com/tronprotocol/tron-docker/issues). For general questions, please use [Discord](https://discord.gg/cGKSsRVCGm) or [Telegram](https://t.me/TronOfficialDevelopersGroupEn).

tools/gradlew/settings.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ include('docker')
33
project(':docker').projectDir = new File(rootDir, '../docker')
44
include('toolkit')
55
project(':toolkit').projectDir = new File(rootDir, '../toolkit')
6+
include('stress-test')
7+
project(':stress-test').projectDir = new File(rootDir, '../stress_test')

tools/stress_test/README.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
## Stress Test Tool
2+
The stress testing tool is designed to evaluate the performance of the `java-tron` fullnode.
3+
It can generate a large volume of transactions, store them locally, and broadcast them to the test network.
4+
Finally, it provides a TPS (Transactions Per Second) report as the stress test result.
5+
6+
### Build the stress test tool
7+
To build the stress test tool, we need to execute the following commands:
8+
```shell script
9+
# clone the tron-docker
10+
git clone https://github.com/tronprotocol/tron-docker.git
11+
# enter the directory
12+
cd tron-docker/tools/gradlew
13+
# compile the stress test tool
14+
./gradlew :stress-test:build
15+
# execute full command
16+
java -jar ../stress_test/build/libs/stresstest.jar help
17+
```
18+
The stress test tool includes four components:
19+
- `collect`: Collect the address list from the account database.
20+
- `generate`: Generate plenty of transactions used the in the stress test.
21+
- `broadcast`: Broadcast the transactions and compute the TPS.
22+
- `statistic`: Compute the TPS from specified block range.
23+
24+
All the configurations of the components are placed in the `stress.conf`, please refer [stress.conf](./src/main/resources/stress.conf)
25+
as an example.
26+
27+
### Collect Address List
28+
`collect` subcommand is used to collect the addresses from the database, which act as `to` addresses when generating
29+
the transactions. The corresponding configuration is:
30+
```
31+
collectAddress = {
32+
total = 1000000
33+
dbPath = "/path/to/output-directory"
34+
}
35+
```
36+
- `total`: denotes the total addresses number we need to collect.
37+
- `dbPath`: denotes the database path
38+
39+
Then we can execute the following `collect` subcommand:
40+
41+
```shell
42+
# execute full command
43+
java -jar /path/to/stresstest.jar collect -c /path/to/stress.conf
44+
# check the log
45+
tail -f logs/stress_test.log
46+
```
47+
The collected addresses are stored in `address-list.csv` file of the current directory.
48+
49+
### Generate the transactions
50+
`generate` subcommand is used to generate plenty of transactions used for the stress test.
51+
The corresponding configuration is:
52+
```
53+
generateTx = {
54+
enable = true
55+
totalTxCnt = 600000
56+
singleTaskTxCount = 100000
57+
txType = {
58+
transfer = 60
59+
transferTrc10 = 10
60+
transferTrc20 = 30
61+
}
62+
updateRefUrl = "127.0.0.1:50051"
63+
// TRY18iTFy6p8yhWiCt1dhd2gz2c15ungq3
64+
privateKey = "aab926e86a17f0f46b4d22e61725edd5770a5b0fbdabb04b0f46ee499b1e34f2"
65+
addressListFile = "/path/to/address-list.csv"
66+
trc10Id = 1000001
67+
trc20Address = "TR7NHqjeKQxGTCi8q8ZY4pL8otSzgjLj6t"
68+
}
69+
```
70+
Here is the introduction for the configuration options:
71+
72+
`enable`: configure whether to generate the transactions;
73+
74+
`totalTxCnt`: configure the total generated transactions count;
75+
76+
`singleTaskTxCount`: configure the transaction count for single task;
77+
78+
`txType`: configure the generated transaction type and proportion. Currently, the supported transaction type
79+
including `transfer`, `transferTrc10`, `transferTrc20`. The sum of all transaction type proportion must be equal 100;
80+
81+
`updateRefUrl`: configure the url which is used to update the `refBlockNum` and `refBlockNum` when generating the transactions;
82+
83+
`privateKey`: configure the private key used to sign the transactions;
84+
85+
`addressListFile`: configure the file path of receiver address list used to build the transactions;
86+
87+
`trc10Id`: configure the TRC10 id used to build the `transferTrc10` transactions;
88+
89+
`trc20ContractAddress`: configure the TRC20 contract address used to build the `transferTrc20` transactions;
90+
91+
Then we can execute the following `generate` subcommand:
92+
93+
```shell
94+
# execute full command
95+
nohup java -jar /path/to/stresstest.jar generate -c /path/to/stress.conf >> start.log 2>&1 &
96+
# check the log
97+
tail -f logs/stress_test.log
98+
```
99+
The generated transactions are stored in the `generate-tx*.csv` files in current `stress-test-output` directory.
100+
101+
*Note*: the expiration time of the generated transactions is 24 hours, which means you need to broadcast the stored transactions in 24 hours.
102+
103+
### Broadcast the transactions
104+
`broadcast` subcommand is used to broadcast the transactions and compute the TPS for the stress test.
105+
The corresponding configuration is:
106+
```
107+
broadcastTx = {
108+
generateTx = true
109+
relayTx = false
110+
tpsLimit = 3000
111+
saveTxId = true
112+
}
113+
```
114+
- `generateTx`: configure whether to broadcast the generated the transactions;
115+
116+
- `relayTx`: configure whether to broadcast the relayed transactions;
117+
118+
- `broadcastUrl`: configure the broadcast url list;
119+
120+
- `tpsLimit`: configure the maximum broadcast transactions per second;
121+
122+
- `saveTxId`: configure whether to save the transaction id of the broadcast transactions.
123+
124+
*Note*: we can use the [dbfork](../toolkit/DbFork.md) tool to get enough `TRX/TRC10/TRC20` balances of address corresponding
125+
to the `privateKey` for the stress test.
126+
127+
Then we can execute the following `generate` subcommand:
128+
129+
```shell
130+
# execute full command
131+
nohup java -jar ../stress_test/build/libs/stresstest.jar broadcast -c /path/to/stress.conf \
132+
--fn-config /path/to/config.conf -d /path/to/output-directory >> start.log 2>&1 &
133+
# check the log
134+
tail -f logs/stress_test.log
135+
```
136+
- `--fn-config`: configure the `java-tron` network we need to connect, please refer [config.conf](./src/main/resources/config.conf)
137+
as an example. Make sure to configure the correct `p2p.version` and `seed.node` options.
138+
139+
- `-d`: configure the `java-tron` database. Before executing the broadcasting process, `broadcast` component
140+
needs to sync with the connected network. So we'd better copy the database from the connected network.
141+
142+
If you set `saveTxId = true`, the broadcast transactions ids will be stored
143+
in the `broadcast-txID*.csv` files in current `stress-test-output` directory.
144+
145+
After broadcasting all the transactions, it will generate the `stress-test-output/broadcast-generate-result`
146+
file to report the stress-test statistic result. For example:
147+
```
148+
Stress test report:
149+
broadcast tps limit: 3000
150+
statistic block range: startBlock: 67926067, endBlock: 67926133
151+
total generate tx count: 600000, total broadcast tx count: 580862, tx on chain rate: 0.968103
152+
cost time: 3.300000 minutes
153+
max block size: 9615
154+
min block size: 3001
155+
tps: 2933.646484
156+
miss block rate: 0.000000
157+
```
158+
The above the result shows the stress test TPS has reached `2933`.
159+
160+
## Relay and Broadcast
161+
If you want to relay the transactions from other network, you need to set `relayTrx.enable = true` and
162+
other related the parameters:
163+
```
164+
relayTx = {
165+
enable = false
166+
url = "grpc.trongrid.io:50051"
167+
startBlockNumber = 59720000
168+
endBlockNumber = 59720500
169+
}
170+
```
171+
- `enable`: configure whether to relay the transactions from other network and save them locally.
172+
- `url`: configure the url to indicate the network the relayed transactions come from;
173+
- `startBlockNumber`: configure the start block number of range for the relayed transactions;
174+
- `endBlockNumber`: configure the end block number of range for the relayed transactions;
175+
176+
Then we can execute the `generate` subcommand.
177+
```shell
178+
# execute full command
179+
nohup java -jar /path/to/stresstest.jar generate -c /path/to/stress.conf >> start.log 2>&1 &
180+
# check the log
181+
tail -f logs/stress_test.log
182+
```
183+
The relayed transactions will be stored in the `relay-tx.csv` file in current `stress-test-output` directory.
184+
185+
To broadcast the relayed transactions, we need set `relayTx = true` and execute the `broadcast` subcommand,
186+
which will broadcast the transactions stored in the `relay-tx.csv` file.
187+
188+
*Warn*: Most of the relayed transactions may be illegal in the stress test network. You need to change the
189+
transaction verification condition in `java-tron` source code to replay the transactions.
190+
191+
## TPS statistic
192+
If the above the `broadcast` subcommand doesn't output `broadcast-generate-result` statistic result,
193+
we can still compute the TPS from specified block range by executing the `statistic` subcommand:
194+
195+
```
196+
statistic = {
197+
url = "127.0.0.1:50051"
198+
startBlockNumber = 68599177
199+
endBlockNumber = 68599689
200+
}
201+
```
202+
- `url`: configure the url to indicate the network for the TPS statistic;
203+
- `startBlockNumber`: configure the start block number of range for the TPS statistic;
204+
- `endBlockNumber`: configure the end block number of range for the TPS statistic;
205+
206+
Then we can execute the `statistic` subcommand.
207+
```
208+
# execute full command
209+
java -jar ../stress_test/build/libs/stresstest.jar statistic -c /path/to/stress.conf -o tps-statistic-result
210+
# check the log
211+
tail -f logs/stress_test.log
212+
```
213+
The TPS statistic result will be saved in the `tps-statistic-result` file of current directory, which is same
214+
with the `broadcast` subcommand statistic result.

tools/stress_test/build.gradle

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
plugins {
2+
// Apply the application plugin to add support for building a CLI application in Java.
3+
id 'java'
4+
id 'application'
5+
id 'checkstyle'
6+
id 'com.github.johnrengelman.shadow' version '7.1.2'
7+
}
8+
9+
sourceCompatibility = JavaVersion.VERSION_1_8
10+
targetCompatibility = JavaVersion.VERSION_1_8
11+
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
12+
13+
repositories {
14+
mavenLocal()
15+
mavenCentral()
16+
maven { url 'https://repo.spring.io/plugins-release' }
17+
maven { url 'https://jitpack.io' }
18+
}
19+
20+
tasks.named('jar') {
21+
enabled = false
22+
dependsOn shadowJar
23+
}
24+
25+
shadowJar {
26+
archiveBaseName.set('stresstest')
27+
archiveClassifier.set('')
28+
archiveVersion.set('')
29+
mergeServiceFiles()
30+
}
31+
32+
dependencies {
33+
// Use JUnit test framework.
34+
testImplementation 'junit:junit:4.13.2'
35+
36+
implementation "com.google.guava:guava:33.0.0-jre"
37+
implementation "io.grpc:grpc-netty-shaded:1.60.0"
38+
implementation "io.grpc:grpc-netty:1.60.0"
39+
implementation "io.grpc:grpc-okhttp:1.60.0"
40+
implementation "io.grpc:grpc-protobuf:1.60.0"
41+
implementation "io.grpc:grpc-stub:1.60.0"
42+
implementation "com.google.protobuf:protobuf-java-util:3.25.5"
43+
implementation "org.bouncycastle:bcprov-jdk18on:1.78.1"
44+
implementation "io.netty:netty-all:4.1.100.Final"
45+
implementation("io.github.317787106:trident:0.9.2.5")
46+
implementation group: 'com.typesafe', name: 'config', version: '1.3.2'
47+
// implementation 'ch.qos.logback:logback-classic:1.2.6'
48+
49+
implementation group: 'info.picocli', name: 'picocli', version: '4.6.3'
50+
compileOnly 'org.projectlombok:lombok:1.18.12'
51+
annotationProcessor 'org.projectlombok:lombok:1.18.12'
52+
testCompileOnly 'org.projectlombok:lombok:1.18.12'
53+
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'
54+
55+
implementation('com.github.tronprotocol.java-tron:framework:GreatVoyage-v4.7.7') {
56+
exclude group: 'com.fasterxml.jackson', module: 'jackson-bom'
57+
exclude group: "pull-parser", module: "pull-parser"
58+
exclude group: "ch.qos.logback", module: "logback-classic"
59+
}
60+
implementation platform('com.fasterxml.jackson:jackson-bom:2.14.0')
61+
implementation(project(":toolkit")) {
62+
exclude group: "org.slf4j", module: "slf4j-api"
63+
exclude group: "ch.qos.logback", module: "logback-classic"
64+
}
65+
implementation files('../toolkit/build/libs/Toolkit.jar')
66+
}
67+
68+
application {
69+
// Define the main class for the application.
70+
mainClass = 'org.tron.StressTest'
71+
}
72+
73+
jar {
74+
manifest {
75+
attributes(
76+
'Main-Class': 'org.tron.StressTest'
77+
)
78+
}
79+
}
80+
81+
checkstyle {
82+
toolVersion = '8.41'
83+
configFile = file("../../conf/checkstyle/checkStyle.xml")
84+
}
85+
86+
task checkstylekStressMain(type: Checkstyle) {
87+
source 'src/main/java'
88+
include '**/*.java'
89+
exclude '**/generated/**'
90+
classpath = files()
91+
ignoreFailures = false
92+
}
93+
94+
task checkstyleStressTest(type: Checkstyle) {
95+
source 'src/test/java'
96+
include '**/*.java'
97+
exclude '**/generated/**'
98+
classpath = files()
99+
ignoreFailures = false
100+
}
101+
102+
check.dependsOn checkstylekStressMain, checkstyleStressTest

tools/stress_test/lombok.config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
lombok.log.fieldName=logger

0 commit comments

Comments
 (0)