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:
Julien Riou 2022-10-18 23:46:47 +02:00
parent bdab5cc5a4
commit c43270a1d4
No known key found for this signature in database
GPG key ID: FF42D23B580C89F7
6 changed files with 61 additions and 7 deletions

View file

@ -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)
}

View file

@ -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()
}

View file

@ -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
View file

@ -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
View file

@ -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=

View file

@ -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() {