feat: Add average query time
- Add debug messages - Use mutex to compute statistics - Add UUID to identify database connections - Fix connection handling for MySQL Signed-off-by: Julien Riou <julien@riou.xyz>
This commit is contained in:
parent
bdab5cc5a4
commit
c43270a1d4
6 changed files with 61 additions and 7 deletions
14
benchmark.go
14
benchmark.go
|
@ -3,6 +3,8 @@ package main
|
|||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Benchmark to store benchmark state
|
||||
|
@ -42,6 +44,7 @@ func (b *Benchmark) Run() {
|
|||
// Queries returns the number of executed queries during the benchmark
|
||||
func (b *Benchmark) Queries() (queries float64) {
|
||||
for _, database := range b.databases {
|
||||
log.Debugf("Connection %s: Queries: %.f", database.ID, database.Queries())
|
||||
queries = queries + database.Queries()
|
||||
}
|
||||
return
|
||||
|
@ -51,3 +54,14 @@ func (b *Benchmark) Queries() (queries float64) {
|
|||
func (b *Benchmark) QueriesPerSecond() float64 {
|
||||
return b.Queries() / b.duration.Seconds()
|
||||
}
|
||||
|
||||
// AverageQueryTime computes the average query execution time for all databases connections in the benchmark
|
||||
func (b *Benchmark) AverageQueryTime() time.Duration {
|
||||
var latencies time.Duration
|
||||
for _, database := range b.databases {
|
||||
log.Debugf("Connection %s: Latency: %s", database.ID, database.AverageQueryTime())
|
||||
latencies = latencies + database.AverageQueryTime()
|
||||
}
|
||||
latency := int64(latencies) / int64(len(b.databases))
|
||||
return time.Duration(latency)
|
||||
}
|
||||
|
|
|
@ -97,14 +97,15 @@ func (c *Config) parsePostgresDSN() string {
|
|||
|
||||
func (c *Config) parseMysqlDSN() (dsn string) {
|
||||
config := mysql.NewConfig()
|
||||
config.Timeout = 1 * time.Second
|
||||
config.Addr = c.Host
|
||||
if c.Port != 0 {
|
||||
config.Net = "tcp"
|
||||
config.Addr += fmt.Sprintf(":%d", c.Port)
|
||||
}
|
||||
config.User = c.User
|
||||
config.Passwd = c.Password
|
||||
config.DBName = c.Database
|
||||
config.TLSConfig = c.TLS
|
||||
|
||||
return config.FormatDSN()
|
||||
}
|
||||
|
|
34
database.go
34
database.go
|
@ -2,19 +2,27 @@ package main
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// Database to store a single connection to the database and its statistics
|
||||
type Database struct {
|
||||
ID uuid.UUID
|
||||
db *sql.DB
|
||||
driver string
|
||||
dsn string
|
||||
query string
|
||||
reconnect bool
|
||||
queries float64
|
||||
|
||||
queries float64 // Total number of queries
|
||||
queriesLock *sync.Mutex
|
||||
|
||||
queriesDuration time.Duration // Time spent executing queries
|
||||
queriesDurationLock *sync.Mutex
|
||||
}
|
||||
|
||||
// NewDatabase creates a single connection to the database then returns the struct
|
||||
|
@ -29,6 +37,9 @@ func NewDatabase(driver string, dsn string, query string, reconnect bool) (*Data
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
database.ID = uuid.New()
|
||||
database.queriesLock = &sync.Mutex{}
|
||||
database.queriesDurationLock = &sync.Mutex{}
|
||||
return database, nil
|
||||
}
|
||||
|
||||
|
@ -63,6 +74,7 @@ func (d *Database) Run(duration time.Duration, wg *sync.WaitGroup) error {
|
|||
if end.Before(time.Now()) {
|
||||
break
|
||||
}
|
||||
queryStart := time.Now()
|
||||
result, err := d.db.Query(d.query)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed query the database: %v", err)
|
||||
|
@ -71,7 +83,20 @@ func (d *Database) Run(duration time.Duration, wg *sync.WaitGroup) error {
|
|||
log.Fatalf("Failed to close query: %v", err)
|
||||
}
|
||||
|
||||
queryDuration := time.Now().Sub(queryStart)
|
||||
|
||||
// Update statistics
|
||||
d.queriesLock.Lock()
|
||||
d.queries++
|
||||
d.queriesLock.Unlock()
|
||||
|
||||
d.queriesDurationLock.Lock()
|
||||
d.queriesDuration = d.queriesDuration + queryDuration
|
||||
d.queriesDurationLock.Unlock()
|
||||
|
||||
// Print debug statistics
|
||||
log.Debugf("Connection %s: Number of queries: %.f | Query duration: %s | Running sum of queries duration: %s", d.ID, d.queries, queryDuration, d.queriesDuration)
|
||||
|
||||
if d.reconnect {
|
||||
if err = d.disconnect(); err != nil {
|
||||
return err
|
||||
|
@ -89,3 +114,8 @@ func (d *Database) Run(duration time.Duration, wg *sync.WaitGroup) error {
|
|||
func (d *Database) Queries() float64 {
|
||||
return d.queries
|
||||
}
|
||||
|
||||
// AverageQueryTime returns the average query execution time in milliseconds
|
||||
func (d *Database) AverageQueryTime() time.Duration {
|
||||
return d.queriesDuration / time.Duration(d.queries)
|
||||
}
|
||||
|
|
9
go.mod
9
go.mod
|
@ -7,9 +7,10 @@ require (
|
|||
github.com/lib/pq v1.10.7
|
||||
)
|
||||
|
||||
require gopkg.in/yaml.v2 v2.4.0
|
||||
|
||||
require (
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
)
|
||||
|
||||
require golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
|
||||
|
|
6
go.sum
6
go.sum
|
@ -1,13 +1,18 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
|
||||
github.com/lib/pq v1.10.7/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
@ -15,4 +20,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+
|
|||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
2
main.go
2
main.go
|
@ -83,6 +83,8 @@ func main() {
|
|||
benchmark.Run()
|
||||
fmt.Printf("Queries: %.0f\n", benchmark.Queries())
|
||||
fmt.Printf("Queries per second: %.0f\n", benchmark.QueriesPerSecond())
|
||||
fmt.Printf("Average query time: %s\n", benchmark.AverageQueryTime())
|
||||
fmt.Printf("Average query time (ms): %d\n", benchmark.AverageQueryTime().Milliseconds())
|
||||
}
|
||||
|
||||
func showVersion() {
|
||||
|
|
Loading…
Reference in a new issue