Skip to content

Commit 189cb6a

Browse files
committed
Refine benchmark
1 parent 027d22c commit 189cb6a

1 file changed

Lines changed: 164 additions & 57 deletions

File tree

cmd/mpcium-benchmark/main.go

Lines changed: 164 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ type BenchmarkResult struct {
2727
MedianTime time.Duration
2828
OperationTimes []time.Duration
2929
ErrorRate float64
30-
OperationsPerSec float64
30+
OperationsPerMin float64
31+
BatchSize int
32+
TotalBatches int
33+
BatchTimes []time.Duration
3134
}
3235

3336
func main() {
@@ -80,6 +83,12 @@ func keygenBenchmarkCommand() *cli.Command {
8083
Value: 30,
8184
Aliases: []string{"t"},
8285
},
86+
&cli.IntFlag{
87+
Name: "batch-size",
88+
Usage: "Number of operations per batch",
89+
Value: 10,
90+
Aliases: []string{"b"},
91+
},
8392
},
8493
}
8594
}
@@ -97,6 +106,12 @@ func ecdsaSignBenchmarkCommand() *cli.Command {
97106
Value: 30,
98107
Aliases: []string{"t"},
99108
},
109+
&cli.IntFlag{
110+
Name: "batch-size",
111+
Usage: "Number of operations per batch",
112+
Value: 10,
113+
Aliases: []string{"b"},
114+
},
100115
},
101116
}
102117
}
@@ -114,6 +129,12 @@ func eddsaSignBenchmarkCommand() *cli.Command {
114129
Value: 30,
115130
Aliases: []string{"t"},
116131
},
132+
&cli.IntFlag{
133+
Name: "batch-size",
134+
Usage: "Number of operations per batch",
135+
Value: 10,
136+
Aliases: []string{"b"},
137+
},
117138
},
118139
}
119140
}
@@ -131,6 +152,12 @@ func reshareBenchmarkCommand() *cli.Command {
131152
Value: 30,
132153
Aliases: []string{"t"},
133154
},
155+
&cli.IntFlag{
156+
Name: "batch-size",
157+
Usage: "Number of operations per batch",
158+
Value: 10,
159+
Aliases: []string{"b"},
160+
},
134161
&cli.IntFlag{
135162
Name: "new-threshold",
136163
Usage: "New threshold for resharing",
@@ -156,11 +183,22 @@ func createMPCClient(cmd *cli.Command) (client.MPCClient, error) {
156183
return nil, fmt.Errorf("failed to connect to NATS: %w", err)
157184
}
158185

159-
opts := client.Options{
160-
NatsConn: nc,
186+
// Create a LocalSigner with the provided key path and password
187+
signerOpts := client.LocalSignerOptions{
161188
KeyPath: keyPath,
162189
Password: password,
163190
}
191+
192+
// Default to Ed25519 for event initiator keys
193+
signer, err := client.NewLocalSigner(types.EventInitiatorKeyTypeEd25519, signerOpts)
194+
if err != nil {
195+
return nil, fmt.Errorf("failed to create signer: %w", err)
196+
}
197+
198+
opts := client.Options{
199+
NatsConn: nc,
200+
Signer: signer,
201+
}
164202
return client.NewMPCClient(opts), nil
165203
}
166204

@@ -259,7 +297,7 @@ func runKeygenBenchmark(ctx context.Context, cmd *cli.Command) error {
259297
totalTime := time.Since(startTime)
260298

261299
// Calculate results
262-
benchResult := calculateBenchmarkResult(results, totalTime)
300+
benchResult := calculateBenchmarkResult(results, totalTime, 1, []time.Duration{totalTime})
263301
printBenchmarkResult("Keygen", benchResult)
264302

265303
return nil
@@ -287,13 +325,15 @@ func runSignBenchmark(ctx context.Context, cmd *cli.Command, keyType types.KeyTy
287325
}
288326

289327
timeout := time.Duration(cmd.Int("timeout")) * time.Second
328+
batchSize := cmd.Int("batch-size")
290329

291330
mpcClient, err := createMPCClient(cmd)
292331
if err != nil {
293332
return err
294333
}
295334

296-
fmt.Printf("Starting %s signing benchmark with %d operations for wallet %s...\n", keyTypeName, n, walletID)
335+
totalBatches := (n + batchSize - 1) / batchSize
336+
fmt.Printf("Starting %s signing benchmark with %d operations (%d batches of %d) for wallet %s...\n", keyTypeName, n, totalBatches, batchSize, walletID)
297337

298338
var results []OperationResult
299339
var wg sync.WaitGroup
@@ -322,47 +362,79 @@ func runSignBenchmark(ctx context.Context, cmd *cli.Command, keyType types.KeyTy
322362
return fmt.Errorf("failed to set up result listener: %w", err)
323363
}
324364

325-
// Run operations
365+
// Run operations in batches
326366
startTime := time.Now()
327-
for i := 0; i < n; i++ {
328-
txID := fmt.Sprintf("benchmark-%s-sign-%d-%d", keyTypeName, time.Now().UnixNano(), i)
329-
330-
// Generate random transaction data
331-
txData := make([]byte, 32)
332-
rand.Read(txData)
333-
334-
msg := &types.SignTxMessage{
335-
KeyType: keyType,
336-
WalletID: walletID,
337-
NetworkInternalCode: "benchmark",
338-
TxID: txID,
339-
Tx: txData,
367+
var batchTimes []time.Duration
368+
369+
// Start progress reporting goroutine
370+
progressTicker := time.NewTicker(10 * time.Second)
371+
defer progressTicker.Stop()
372+
go func() {
373+
for range progressTicker.C {
374+
mu.Lock()
375+
completed := 0
376+
for _, r := range results {
377+
if r.Completed {
378+
completed++
379+
}
380+
}
381+
mu.Unlock()
382+
fmt.Printf("Progress: %d/%d results received\n", completed, n)
340383
}
384+
}()
341385

342-
result := OperationResult{
343-
ID: txID,
344-
StartTime: time.Now(),
386+
for batchNum := 0; batchNum < totalBatches; batchNum++ {
387+
batchStart := time.Now()
388+
batchStartIdx := batchNum * batchSize
389+
batchEndIdx := batchStartIdx + batchSize
390+
if batchEndIdx > n {
391+
batchEndIdx = n
345392
}
346393

347-
mu.Lock()
348-
results = append(results, result)
349-
mu.Unlock()
394+
fmt.Printf("Starting batch %d/%d (%d operations)...\n", batchNum+1, totalBatches, batchEndIdx-batchStartIdx)
350395

351-
wg.Add(1)
396+
for i := batchStartIdx; i < batchEndIdx; i++ {
397+
txID := fmt.Sprintf("benchmark-%s-sign-%d-%d", keyTypeName, time.Now().UnixNano(), i)
398+
399+
// Generate random transaction data
400+
txData := make([]byte, 32)
401+
rand.Read(txData)
402+
403+
msg := &types.SignTxMessage{
404+
KeyType: keyType,
405+
WalletID: walletID,
406+
NetworkInternalCode: "benchmark",
407+
TxID: txID,
408+
Tx: txData,
409+
}
410+
411+
result := OperationResult{
412+
ID: txID,
413+
StartTime: time.Now(),
414+
}
352415

353-
err := mpcClient.SignTransaction(msg)
354-
if err != nil {
355416
mu.Lock()
356-
results[i].Completed = true
357-
results[i].Success = false
358-
results[i].ErrorReason = err.Error()
359-
results[i].EndTime = time.Now()
417+
results = append(results, result)
360418
mu.Unlock()
361-
wg.Done()
419+
420+
wg.Add(1)
421+
422+
err := mpcClient.SignTransaction(msg)
423+
if err != nil {
424+
mu.Lock()
425+
results[i].Completed = true
426+
results[i].Success = false
427+
results[i].ErrorReason = err.Error()
428+
results[i].EndTime = time.Now()
429+
mu.Unlock()
430+
wg.Done()
431+
}
432+
433+
// Add small delay between operations
434+
time.Sleep(10 * time.Millisecond)
362435
}
363436

364-
// Add small delay between operations
365-
time.Sleep(10 * time.Millisecond)
437+
batchTimes = append(batchTimes, time.Since(batchStart))
366438
}
367439

368440
// Wait for all operations with timeout
@@ -382,7 +454,7 @@ func runSignBenchmark(ctx context.Context, cmd *cli.Command, keyType types.KeyTy
382454
totalTime := time.Since(startTime)
383455

384456
// Calculate results
385-
benchResult := calculateBenchmarkResult(results, totalTime)
457+
benchResult := calculateBenchmarkResult(results, totalTime, batchSize, batchTimes)
386458
printBenchmarkResult(fmt.Sprintf("%s Signing", keyTypeName), benchResult)
387459

388460
return nil
@@ -505,7 +577,7 @@ func runReshareBenchmark(ctx context.Context, cmd *cli.Command) error {
505577
totalTime := time.Since(startTime)
506578

507579
// Calculate results
508-
benchResult := calculateBenchmarkResult(results, totalTime)
580+
benchResult := calculateBenchmarkResult(results, totalTime, 1, []time.Duration{totalTime})
509581
printBenchmarkResult("Reshare", benchResult)
510582

511583
return nil
@@ -533,7 +605,7 @@ func parseNumOps(numOps string) (int, error) {
533605
return n, nil
534606
}
535607

536-
func calculateBenchmarkResult(results []OperationResult, totalTime time.Duration) BenchmarkResult {
608+
func calculateBenchmarkResult(results []OperationResult, totalTime time.Duration, batchSize int, batchTimes []time.Duration) BenchmarkResult {
537609
var operationTimes []time.Duration
538610
successfulOps := 0
539611
failedOps := 0
@@ -577,8 +649,8 @@ func calculateBenchmarkResult(results []OperationResult, totalTime time.Duration
577649
medianTime = operationTimes[len(operationTimes)/2]
578650
}
579651

580-
// Calculate operations per second
581-
operationsPerSec = float64(successfulOps) / totalTime.Seconds()
652+
// Calculate operations per minute
653+
operationsPerSec = float64(successfulOps) / totalTime.Minutes()
582654
}
583655

584656
return BenchmarkResult{
@@ -590,25 +662,60 @@ func calculateBenchmarkResult(results []OperationResult, totalTime time.Duration
590662
MedianTime: medianTime,
591663
OperationTimes: operationTimes,
592664
ErrorRate: errorRate,
593-
OperationsPerSec: operationsPerSec,
665+
OperationsPerMin: operationsPerSec,
666+
BatchSize: batchSize,
667+
TotalBatches: len(batchTimes),
668+
BatchTimes: batchTimes,
594669
}
595670
}
596671

597672
func printBenchmarkResult(operationType string, result BenchmarkResult) {
598-
fmt.Printf("\n=== %s Benchmark Results ===\n", operationType)
599-
fmt.Printf("Total Operations: %d\n", result.TotalOperations)
600-
fmt.Printf("Successful: %d\n", result.SuccessfulOps)
601-
fmt.Printf("Failed: %d\n", result.FailedOps)
602-
fmt.Printf("Error Rate: %.2f%%\n", result.ErrorRate)
603-
fmt.Printf("Total Time: %v\n", result.TotalTime)
604-
fmt.Printf("Average Time/Op: %v\n", result.AverageTime)
605-
fmt.Printf("Median Time/Op: %v\n", result.MedianTime)
606-
fmt.Printf("Operations/Second: %.2f\n", result.OperationsPerSec)
607-
608-
if len(result.OperationTimes) > 0 {
609-
fmt.Printf("Min Time/Op: %v\n", result.OperationTimes[0])
610-
fmt.Printf("Max Time/Op: %v\n", result.OperationTimes[len(result.OperationTimes)-1])
611-
}
612-
613-
fmt.Println("=====================================")
673+
fmt.Println()
674+
fmt.Println("===============================")
675+
fmt.Printf("BENCHMARK RESULTS SUMMARY\n")
676+
fmt.Println("===============================")
677+
fmt.Printf("Total benchmark time: %v\n", result.TotalTime)
678+
fmt.Printf("Total batches sent: %d\n", result.TotalBatches)
679+
fmt.Printf("Total requests sent: %d\n", result.TotalOperations)
680+
fmt.Printf("Successful completions: %d\n", result.SuccessfulOps)
681+
fmt.Printf("Success rate: %.2f%%\n", 100.0-result.ErrorRate)
682+
fmt.Printf("Average signs per minute: %.2f\n", result.OperationsPerMin)
683+
684+
fmt.Println()
685+
fmt.Println("------------------------------")
686+
fmt.Printf("%d REQUEST ANALYSIS\n", result.BatchSize)
687+
fmt.Println("------------------------------")
688+
689+
if len(result.OperationTimes) >= result.BatchSize {
690+
firstNResults := result.OperationTimes[:result.BatchSize]
691+
if len(firstNResults) > len(result.OperationTimes) {
692+
firstNResults = result.OperationTimes
693+
}
694+
695+
completedCount := len(firstNResults)
696+
if completedCount > result.BatchSize {
697+
completedCount = result.BatchSize
698+
}
699+
700+
fmt.Printf("Completed from first %d: %d/%d\n", result.BatchSize, completedCount, result.BatchSize)
701+
702+
if len(firstNResults) > 0 {
703+
var totalTime time.Duration
704+
minTime := firstNResults[0]
705+
maxTime := firstNResults[0]
706+
707+
for _, t := range firstNResults {
708+
totalTime += t
709+
if t < minTime {
710+
minTime = t
711+
}
712+
if t > maxTime {
713+
maxTime = t
714+
}
715+
}
716+
717+
fmt.Printf("Fastest (first %d): %v\n", result.BatchSize, minTime)
718+
fmt.Printf("Slowest (first %d): %v\n", result.BatchSize, maxTime)
719+
}
720+
}
614721
}

0 commit comments

Comments
 (0)