Skip to content

Commit d12dd4a

Browse files
Feat/Iteratively compute the Maximum Sustainable Throughput (#15)
* iteratively calc Maximum Sustainable Throughput * add logs * refactor(tx_pool_throughput_analysis): improve variable naming for clarity in throughput calculations * refactor(tx_pool_throughput_analysis): update throughput test parameters to range from 500 to 2000 TPS with 250 TPS increments and reduced duration * refactor(tx_pool_throughput_analysis): expand throughput test parameters to cover a range from 100 to 1000 TPS and from 1000 to 5000 TPS with adjusted durations and increments * refactor(tx_pool_throughput_analysis): remove unused percentile parameter from throughput measurement function * fix(build-release.yml): update wiki links and release artifact URLs to reflect new repository ownership * refactor(tx_pool_throughput_analysis): increase timeout for throughput analysis from 5m to 15m * prepare for percentile usage * refactor(tx_pool_throughput_analysis): move logging of percentile usage to the correct position in the function --------- Co-authored-by: tosettil-polimi <info@tosettil.me>
1 parent 560eb25 commit d12dd4a

File tree

5 files changed

+107
-51
lines changed

5 files changed

+107
-51
lines changed

.github/workflows/build-release.yml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,14 +68,14 @@ jobs:
6868
${{ steps.changelog.outputs.changelog }}
6969
7070
### Release Artifacts
71-
Please read through the [wiki](https://github.com/noku-team/assertoor/wiki) for setup & configuration instructions.
71+
Please read through the [wiki](https://github.com/erigontech/assertoor/wiki) for setup & configuration instructions.
7272
| Release File | Description |
7373
| ------------- | ------------- |
74-
| [assertoor_${{ inputs.version }}_windows_amd64.zip](https://github.com/noku-team/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_windows_amd64.zip) | assertoor executables for windows/amd64 |
75-
| [assertoor_${{ inputs.version }}_linux_amd64.tar.gz](https://github.com/noku-team/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_linux_amd64.tar.gz) | assertoor executables for linux/amd64 |
76-
| [assertoor_${{ inputs.version }}_linux_arm64.tar.gz](https://github.com/noku-team/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_linux_arm64.tar.gz) | assertoor executables for linux/arm64 |
77-
| [assertoor_${{ inputs.version }}_darwin_amd64.tar.gz](https://github.com/noku-team/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_darwin_amd64.tar.gz) | assertoor executable for macos/amd64 |
78-
| [assertoor_${{ inputs.version }}_darwin_arm64.tar.gz](https://github.com/noku-team/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_darwin_arm64.tar.gz) | assertoor executable for macos/arm64 |
74+
| [assertoor_${{ inputs.version }}_windows_amd64.zip](https://github.com/erigontech/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_windows_amd64.zip) | assertoor executables for windows/amd64 |
75+
| [assertoor_${{ inputs.version }}_linux_amd64.tar.gz](https://github.com/erigontech/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_linux_amd64.tar.gz) | assertoor executables for linux/amd64 |
76+
| [assertoor_${{ inputs.version }}_linux_arm64.tar.gz](https://github.com/erigontech/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_linux_arm64.tar.gz) | assertoor executables for linux/arm64 |
77+
| [assertoor_${{ inputs.version }}_darwin_amd64.tar.gz](https://github.com/erigontech/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_darwin_amd64.tar.gz) | assertoor executable for macos/amd64 |
78+
| [assertoor_${{ inputs.version }}_darwin_arm64.tar.gz](https://github.com/erigontech/assertoor/releases/download/v${{ inputs.version }}/assertoor_${{ inputs.version }}_darwin_arm64.tar.gz) | assertoor executable for macos/arm64 |
7979
env:
8080
GITHUB_TOKEN: ${{ github.token }}
8181

pkg/coordinator/tasks/tx_pool_throughput_analysis/config.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ package txpoolthroughputanalysis
33
type Config struct {
44
PrivateKey string `yaml:"privateKey" json:"privateKey"`
55

6-
TPS int `yaml:"tps" json:"tps"`
6+
StartingTPS int `yaml:"tps" json:"tps"`
7+
EndingTPS int `yaml:"endingTps" json:"endingTps"`
8+
IncrementTPS int `yaml:"incrementTps" json:"incrementTps"`
79
DurationS int `yaml:"durationS" json:"durationS"`
810
LogInterval int `yaml:"logInterval" json:"logInterval"`
911
SecondsBeforeRunning int `yaml:"secondsBeforeRunning" json:"secondsBeforeRunning"`
1012
}
1113

1214
func DefaultConfig() Config {
1315
return Config{
14-
TPS: 100,
16+
StartingTPS: 100,
17+
EndingTPS: 1000,
18+
IncrementTPS: 100,
1519
DurationS: 60,
1620
LogInterval: 100,
1721
SecondsBeforeRunning: 0,

pkg/coordinator/tasks/tx_pool_throughput_analysis/task.go

Lines changed: 78 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"crypto/rand"
66
"encoding/json"
7+
"errors"
78
"fmt"
89
"math/big"
910
"time"
@@ -25,6 +26,11 @@ var (
2526
}
2627
)
2728

29+
type ThroughoutMeasure struct {
30+
LoadTPS int `json:"load_tps"`
31+
ProcessedTPS int `json:"processed_tps"`
32+
}
33+
2834
type Task struct {
2935
ctx *types.TaskContext
3036
options *types.TaskOptions
@@ -102,8 +108,8 @@ func (t *Task) Execute(ctx context.Context) error {
102108
client := executionClients[n.Int64()]
103109

104110
t.logger.Infof("Measuring TxPool transaction propagation *throughput*")
105-
t.logger.Infof("Targeting client: %s, TPS: %d, Duration: %d seconds",
106-
client.GetName(), t.config.TPS, t.config.DurationS)
111+
t.logger.Infof("Targeting client: %s, Starting TPS: %d, Ending TPS: %d, Increment TPS: %d, Duration: %d seconds",
112+
client.GetName(), t.config.StartingTPS, t.config.EndingTPS, t.config.IncrementTPS, t.config.DurationS)
107113

108114
// Wait for the specified seconds before starting the task
109115
if t.config.SecondsBeforeRunning > 0 {
@@ -117,19 +123,69 @@ func (t *Task) Execute(ctx context.Context) error {
117123
}
118124
}
119125

120-
// Prepare to collect transaction latencies
121-
testDeadline := time.Now().Add(time.Duration(t.config.DurationS+60*30) * time.Second)
122-
126+
// Create a new load target for the transaction propagation measurement
123127
loadTarget := txloadtool.NewLoadTarget(ctx, t.ctx, t.logger, t.wallet, client)
124-
load := txloadtool.NewLoad(loadTarget, t.config.TPS, t.config.DurationS, testDeadline, t.config.LogInterval)
128+
129+
percentile := 0.99 // 0.95 should be enough, change in the future if needed
130+
singleMeasureDeadline := time.Now().Add(time.Duration(t.config.DurationS+60*30) * time.Second)
131+
132+
// slice of pairs: sending tps, processed TPS values
133+
var throughoutMeasures []ThroughoutMeasure
134+
135+
// Iterate over the TPS range and crate a plot processedTps vs sendingTps
136+
t.logger.Infof("Iterating over the TPS range, starting TPS: %d, ending TPS: %d, increment TPS: %d",
137+
t.config.StartingTPS, t.config.EndingTPS, t.config.IncrementTPS)
138+
139+
for sendingTps := t.config.StartingTPS; sendingTps <= t.config.EndingTPS; sendingTps += t.config.IncrementTPS {
140+
// measure the throughput with the current sendingTps
141+
processedTps, err := t.measureTpsWithLoad(loadTarget, sendingTps, t.config.DurationS, singleMeasureDeadline, percentile)
142+
if err != nil {
143+
t.logger.Errorf("Error during throughput measurement with sendingTps=%d, duration=%d: %v", sendingTps, t.config.DurationS, err)
144+
t.ctx.SetResult(types.TaskResultFailure)
145+
146+
return err
147+
}
148+
149+
// add to throughoutMeasures
150+
throughoutMeasures = append(throughoutMeasures, ThroughoutMeasure{
151+
LoadTPS: sendingTps,
152+
ProcessedTPS: processedTps,
153+
})
154+
}
155+
156+
t.logger.Infof("Finished measuring throughput, collected %d measures", len(throughoutMeasures))
157+
158+
// Set the throughput measures in the task context outputs
159+
// from this plot we can compute the Maximum Sustainable Throughput or Capacity limit
160+
t.ctx.Outputs.SetVar("throughput_measures", throughoutMeasures) // log coordinated_omission_event_count and missed_p2p_event_count?
161+
162+
outputs := map[string]interface{}{
163+
"throughput_measures": throughoutMeasures,
164+
}
165+
166+
outputsJSON, _ := json.Marshal(outputs)
167+
t.logger.Infof("outputs_json: %s", string(outputsJSON))
168+
169+
// Set the task result to success
170+
t.ctx.SetResult(types.TaskResultSuccess)
171+
172+
return nil
173+
}
174+
175+
func (t *Task) measureTpsWithLoad(loadTarget *txloadtool.LoadTarget, sendingTps, durationS int,
176+
testDeadline time.Time, percentile float64) (int, error) {
177+
t.logger.Infof("Single measure of throughput, sending TPS: %d, duration: %d secs", sendingTps, durationS)
178+
179+
// Prepare to collect transaction latencies
180+
load := txloadtool.NewLoad(loadTarget, sendingTps, durationS, testDeadline, t.config.LogInterval)
125181

126182
// Generate and sending transactions, waiting for their propagation
127183
execErr := load.Execute()
128184
if execErr != nil {
129185
t.logger.Errorf("Error during transaction load execution: %v", execErr)
130186
t.ctx.SetResult(types.TaskResultFailure)
131187

132-
return execErr
188+
return 0, execErr
133189
}
134190

135191
// Collect the transactions and their latencies
@@ -138,12 +194,12 @@ func (t *Task) Execute(ctx context.Context) error {
138194
t.logger.Errorf("Error measuring transaction propagation latencies: %v", measureErr)
139195
t.ctx.SetResult(types.TaskResultFailure)
140196

141-
return measureErr
197+
return 0, measureErr
142198
}
143199

144200
// Check if the context was cancelled or other errors occurred
145201
if result.Failed {
146-
return fmt.Errorf("error measuring transaction propagation latencies: load failed")
202+
return 0, fmt.Errorf("error measuring transaction propagation latencies: load failed")
147203
}
148204

149205
// Send txes to other clients, for speeding up tx mining
@@ -166,33 +222,23 @@ func (t *Task) Execute(ctx context.Context) error {
166222

167223
t.logger.Infof("Total transactions sent: %d", result.TotalTxs)
168224

169-
// Calculate statistics
225+
if percentile != 0.99 {
226+
// Calculate the percentile of latencies using result.LatenciesMus
227+
// Not implemented yet
228+
notImpl := errors.New("percentile selection not implemented, use 0.99")
229+
return 0, notImpl
230+
}
231+
232+
t.logger.Infof("Using 0.99 percentile for latency calculation")
233+
170234
t.logger.Infof("Last measure delay since start time: %s", result.LastMeasureDelay)
171235

172-
processedTxPerSecond := float64(result.TotalTxs) / result.LastMeasureDelay.Seconds()
236+
processedTpsF := float64(result.TotalTxs) / result.LastMeasureDelay.Seconds()
237+
processedTps := int(processedTpsF) // round
173238

174239
t.logger.Infof("Processed %d transactions in %.2fs, mean throughput: %.2f tx/s",
175-
result.TotalTxs, result.LastMeasureDelay.Seconds(), processedTxPerSecond)
240+
result.TotalTxs, result.LastMeasureDelay.Seconds(), processedTpsF)
176241
t.logger.Infof("Sent %d transactions in %.2fs", result.TotalTxs, result.LastMeasureDelay.Seconds())
177242

178-
t.ctx.Outputs.SetVar("mean_tps_throughput", processedTxPerSecond)
179-
t.ctx.Outputs.SetVar("tx_count", result.TotalTxs)
180-
t.ctx.Outputs.SetVar("duplicated_p2p_event_count", result.DuplicatedP2PEventCount)
181-
t.ctx.Outputs.SetVar("missed_p2p_event_count", result.NotReceivedP2PEventCount)
182-
t.ctx.Outputs.SetVar("coordinated_omission_event_count", result.CoordinatedOmissionEventCount)
183-
184-
t.ctx.SetResult(types.TaskResultSuccess)
185-
186-
outputs := map[string]interface{}{
187-
"tx_count": result.TotalTxs,
188-
"mean_tps_throughput": processedTxPerSecond,
189-
"duplicated_p2p_event_count": result.DuplicatedP2PEventCount,
190-
"coordinated_omission_events_count": result.CoordinatedOmissionEventCount,
191-
"missed_p2p_event_count": result.NotReceivedP2PEventCount,
192-
}
193-
194-
outputsJSON, _ := json.Marshal(outputs)
195-
t.logger.Infof("outputs_json: %s", string(outputsJSON))
196-
197-
return nil
243+
return processedTps, nil
198244
}

playbooks/dev/tx-pool-check-short.yaml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,13 @@ tasks:
2020
config:
2121
waitTime: 5
2222
- name: tx_pool_throughput_analysis
23-
title: "Check transaction pool throughput with 10.000 transactions"
23+
title: "Check transaction pool throughput from 500 to 2000 TPS with 250 TPS increment, duration 2s per test"
2424
timeout: 30m
2525
config:
26-
tps: 2000
27-
durationS: 5
26+
startingTps: 500
27+
endingTps: 2000
28+
incrementTps: 250
29+
durationS: 2
2830
logInterval: 1000
2931
configVars:
3032
privateKey: "walletPrivkey"

playbooks/dev/tx-pool-check.yaml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,18 @@ tasks:
2121
waitTime: 5
2222
- name: tx_pool_throughput_analysis
2323
timeout: 5m
24-
title: "Check transaction pool throughput with 1.000 transactions in one second, duration 10s"
24+
title: "Check transaction pool throughput from 100 to 1000 TPS with 100 TPS increment, duration 2s per test"
2525
config:
26-
tps: 1000
27-
durationS: 10
26+
startingTps: 100
27+
endingTps: 1000
28+
incrementTps: 100
29+
durationS: 2
2830
logInterval: 1000
2931
configVars:
3032
privateKey: "walletPrivkey"
3133
- name: tx_pool_clean
3234
title: "Clean transaction pool"
33-
timeout: 5m
35+
timeout: 15m
3436
config:
3537
waitTime: 5
3638
- name: tx_pool_latency_analysis
@@ -48,11 +50,13 @@ tasks:
4850
config:
4951
waitTime: 5
5052
- name: tx_pool_throughput_analysis
51-
timeout: 5m
52-
title: "Check transaction pool throughput with 5.000 transactions in one second, duration 5s"
53+
timeout: 15m
54+
title: "Check transaction pool throughput from 1000 to 5000 TPS with 500 TPS increment, duration 2s per test"
5355
config:
54-
tps: 5000
55-
durationS: 5
56+
startingTps: 1000
57+
endingTps: 5000
58+
incrementTps: 500
59+
durationS: 2
5660
logInterval: 2500
5761
configVars:
5862
privateKey: "walletPrivkey"

0 commit comments

Comments
 (0)