mirror of
https://github.com/hanzo-fi/stack.git
synced 2026-10-30 20:34:43 +00:00
153 lines
4.0 KiB
Go
153 lines
4.0 KiB
Go
package benchmarks
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"math/big"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"os"
|
|
"runtime"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
ledger "github.com/formancehq/ledger/internal"
|
|
"github.com/formancehq/ledger/internal/api/backend"
|
|
v2 "github.com/formancehq/ledger/internal/api/v2"
|
|
"github.com/formancehq/ledger/internal/engine"
|
|
"github.com/formancehq/ledger/internal/opentelemetry/metrics"
|
|
"github.com/formancehq/ledger/internal/storage/storagetesting"
|
|
"github.com/formancehq/stack/libs/go-libs/api"
|
|
"github.com/formancehq/stack/libs/go-libs/auth"
|
|
"github.com/formancehq/stack/libs/go-libs/logging"
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
"go.uber.org/atomic"
|
|
)
|
|
|
|
func BenchmarkParallelWrites(b *testing.B) {
|
|
|
|
ctx := logging.TestingContext()
|
|
|
|
driver := storagetesting.StorageDriver(b)
|
|
resolver := engine.NewResolver(driver, engine.WithLogger(logging.FromContext(ctx)))
|
|
b.Cleanup(func() {
|
|
require.NoError(b, resolver.CloseLedgers(ctx))
|
|
})
|
|
|
|
ledgerName := uuid.NewString()
|
|
|
|
backend := backend.NewDefaultBackend(driver, "latest", resolver)
|
|
router := v2.NewRouter(backend, nil, metrics.NewNoOpRegistry(), auth.NewNoAuth())
|
|
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
ctx := logging.ContextWithLogger(r.Context(), logging.FromContext(ctx))
|
|
router.ServeHTTP(w, r.WithContext(ctx))
|
|
})
|
|
|
|
totalDuration := atomic.Int64{}
|
|
b.SetParallelism(1000)
|
|
runtime.GC()
|
|
b.ResetTimer()
|
|
startOfBench := time.Now()
|
|
counter := atomic.NewInt64(0)
|
|
longestTxLock := sync.Mutex{}
|
|
longestTransactionID := big.NewInt(0)
|
|
longestTransactionDuration := time.Duration(0)
|
|
b.RunParallel(func(pb *testing.PB) {
|
|
buf := bytes.NewBufferString("")
|
|
for pb.Next() {
|
|
buf.Reset()
|
|
id := counter.Add(1)
|
|
|
|
//script := controllers.Script{
|
|
// Script: core.Script{
|
|
// Plain: fmt.Sprintf(`
|
|
// vars {
|
|
// account $account
|
|
// }
|
|
//
|
|
// send [USD/2 100] (
|
|
// source = @world:%d allowing unbounded overdraft
|
|
// destination = $account
|
|
// )`, counter.Load()%100),
|
|
// },
|
|
// Vars: map[string]any{
|
|
// "account": fmt.Sprintf("accounts:%d", counter.Add(1)),
|
|
// },
|
|
//}
|
|
|
|
script := ledger.ScriptV1{
|
|
Script: ledger.Script{
|
|
Plain: `vars {
|
|
account $account
|
|
}
|
|
|
|
send [USD/2 100] (
|
|
source = @world
|
|
destination = $account
|
|
)`,
|
|
},
|
|
Vars: map[string]any{
|
|
"account": fmt.Sprintf("accounts:%d", id),
|
|
},
|
|
}
|
|
|
|
// script := controllers.Script{
|
|
// Script: core.Script{
|
|
// Plain: `vars {
|
|
// account $account
|
|
// account $src
|
|
//}
|
|
//
|
|
//send [USD/2 100] (
|
|
// source = $src allowing unbounded overdraft
|
|
// destination = $account
|
|
//)`,
|
|
// },
|
|
// Vars: map[string]any{
|
|
// "src": fmt.Sprintf("world:%d", id),
|
|
// "account": fmt.Sprintf("accounts:%d", id),
|
|
// },
|
|
// }
|
|
|
|
err := json.NewEncoder(buf).Encode(ledger.TransactionRequest{
|
|
Script: script,
|
|
})
|
|
require.NoError(b, err)
|
|
|
|
//ctx, _ := context.WithDeadline(ctx, time.Now().Add(10*time.Second))
|
|
|
|
req := httptest.NewRequest("POST", "/"+ledgerName+"/transactions", buf)
|
|
req = req.WithContext(ctx)
|
|
req.URL.RawQuery = url.Values{
|
|
"async": []string{os.Getenv("ASYNC")},
|
|
}.Encode()
|
|
rsp := httptest.NewRecorder()
|
|
|
|
now := time.Now()
|
|
handler.ServeHTTP(rsp, req)
|
|
latency := time.Since(now).Milliseconds()
|
|
totalDuration.Add(latency)
|
|
|
|
require.Equal(b, http.StatusOK, rsp.Code)
|
|
tx, _ := api.DecodeSingleResponse[ledger.Transaction](b, rsp.Body)
|
|
|
|
longestTxLock.Lock()
|
|
if time.Millisecond*time.Duration(latency) > longestTransactionDuration {
|
|
longestTransactionID = tx.ID
|
|
longestTransactionDuration = time.Duration(latency) * time.Millisecond
|
|
}
|
|
longestTxLock.Unlock()
|
|
}
|
|
})
|
|
|
|
b.StopTimer()
|
|
b.Logf("Longest transaction: %d (%s)", longestTransactionID, longestTransactionDuration.String())
|
|
b.ReportMetric((float64(time.Duration(b.N))/float64(time.Since(startOfBench)))*float64(time.Second), "t/s")
|
|
b.ReportMetric(float64(totalDuration.Load()/int64(b.N)), "ms/transaction")
|
|
runtime.GC()
|
|
}
|