-
Notifications
You must be signed in to change notification settings - Fork 0
Run persistent tx generation in parallel, cache account balances #37
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
base: main
Are you sure you want to change the base?
Changes from 1 commit
a2935ed
078e05d
416731c
1512623
43e6ba2
bc2c8a1
bf07318
1044f13
f8d07af
ebb7402
35e3877
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -123,32 +123,52 @@ | |
| return len(sentTxs), nil | ||
| } | ||
|
|
||
| func (r *Runner) buildLoadPersistent(msgSpec loadtesttypes.LoadTestMsg, maxLoadSize int, useBaseline bool) ([]*gethtypes.Transaction, error) { | ||
| r.logger.Info("building load", zap.Int("maxLoadSize", maxLoadSize)) | ||
| var txnLoad []*gethtypes.Transaction | ||
| var wg sync.WaitGroup | ||
| txChan := make(chan *gethtypes.Transaction, maxLoadSize) | ||
| for range maxLoadSize { | ||
| sender := r.txFactory.GetNextSender() | ||
| wg.Go(func() { | ||
aljo242 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| sender := r.txFactory.GetNextSender() | ||
|
|
||
| if sender == nil { | ||
| r.logger.Info("failed to get sender") | ||
| break | ||
| } | ||
| nonce, ok := r.nonces.Load(sender.Address()) | ||
| if !ok { | ||
| // this really should not happen ever. better safe than sorry. | ||
| return nil, fmt.Errorf("nonce for wallet %s not found", sender.Address()) | ||
| } | ||
| tx, err := r.txFactory.BuildTxs(msgSpec, sender, nonce.(uint64), useBaseline) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to build txs %w", err) | ||
| } | ||
| lastTx := tx[len(tx)-1] | ||
| if lastTx == nil { | ||
| return nil, nil | ||
| if sender == nil { | ||
| return | ||
| } | ||
| nonce, ok := r.nonces.Load(sender.Address()) | ||
| if !ok { | ||
| // this really should not happen ever. better safe than sorry. | ||
| r.logger.Error("nonce for wallet not found", zap.String("wallet", sender.Address().String())) | ||
| return | ||
| } | ||
| tx, err := r.txFactory.BuildTxs(msgSpec, sender, nonce.(uint64), useBaseline) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. just confirming it is not possible to generate two txs for the same
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. GetNextSender will return nil when it runs out of funded accounts which have not been used already. When we start a new round of load generation we will start over from index 0. Once all wallets are funded we will reset sender and receiver indices to 0 and len(wallets)/2 respectively and iterate through N messages each time, incrementing modulo length of wallets. |
||
| if err != nil { | ||
| r.logger.Error("failed to build txs", zap.Error(err)) | ||
| return | ||
| } | ||
| lastTx := tx[len(tx)-1] | ||
| if lastTx == nil { | ||
| return | ||
| } | ||
| r.nonces.Store(sender.Address(), lastTx.Nonce()+1) | ||
| // Only use single txn builders here | ||
| for _, txn := range tx { | ||
| txChan <- txn | ||
| } | ||
| }) | ||
| } | ||
| doneChan := make(chan struct{}) | ||
| go func() { | ||
| wg.Wait() | ||
| doneChan <- struct{}{} | ||
| }() | ||
| for { | ||
| select { | ||
| case txn := <-txChan: | ||
| txnLoad = append(txnLoad, txn) | ||
| case <-doneChan: | ||
| r.logger.Info("Generated load txs", zap.Int("num_txs", len(txnLoad))) | ||
| return txnLoad, nil | ||
| } | ||
| r.nonces.Store(sender.Address(), lastTx.Nonce()+1) | ||
| // Only use single txn builders here | ||
| txnLoad = append(txnLoad, tx...) | ||
| } | ||
| return txnLoad, nil | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Loop Variable Reference: Concurrency Bug
The loop captures the variable
iby reference in the closure. When the goroutine executes,iwill have the final value from the loop, causing all goroutines to write tosentTxs[len(txs)-1]. Captureiby value in the loop or pass it as a function parameter to ensure each goroutine writes to the correct index.