From 2ef550bc274cae44654a7c32a49af0d2e59451d4 Mon Sep 17 00:00:00 2001 From: Danny van Kooten Date: Sun, 15 Jul 2018 10:05:03 +0200 Subject: [PATCH] reduce number of memory allocations in hot path --- pkg/api/collect.go | 18 +++++++++--------- pkg/datastore/sqlstore/pageviews.go | 25 ++++++++++++++++++++----- 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/pkg/api/collect.go b/pkg/api/collect.go index c38a8a5..c34bc57 100644 --- a/pkg/api/collect.go +++ b/pkg/api/collect.go @@ -153,9 +153,9 @@ func aggregate(db datastore.Datastore) { } func collect(db datastore.Datastore, pageviews chan *models.Pageview) { - var buffer []*models.Pageview var size = 800 var timeout = 600 * time.Millisecond + var buffer = make([]*models.Pageview, 0) for { select { @@ -163,12 +163,12 @@ func collect(db datastore.Datastore, pageviews chan *models.Pageview) { buffer = append(buffer, pageview) if len(buffer) >= size { persist(db, buffer) - buffer = buffer[:0] + buffer = make([]*models.Pageview, 0) } case <-time.After(timeout): if len(buffer) > 0 { persist(db, buffer) - buffer = buffer[:0] + buffer = make([]*models.Pageview, 0) } } } @@ -179,11 +179,11 @@ func persist(db datastore.Datastore, pageviews []*models.Pageview) { updates := make([]*models.Pageview, 0, n) inserts := make([]*models.Pageview, 0, n) - for _, p := range pageviews { - if !p.IsBounce { - updates = append(updates, p) + for i := range pageviews { + if !pageviews[i].IsBounce { + updates = append(updates, pageviews[i]) } else { - inserts = append(inserts, p) + inserts = append(inserts, pageviews[i]) } } @@ -192,11 +192,11 @@ func persist(db datastore.Datastore, pageviews []*models.Pageview) { var err error err = db.InsertPageviews(inserts) if err != nil { - log.Error(err) + log.Errorf("error inserting pageviews: %s", err) } err = db.UpdatePageviews(updates) if err != nil { - log.Error(err) + log.Errorf("error updating pageviews: %s", err) } } diff --git a/pkg/datastore/sqlstore/pageviews.go b/pkg/datastore/sqlstore/pageviews.go index 4b963c1..c1506b1 100644 --- a/pkg/datastore/sqlstore/pageviews.go +++ b/pkg/datastore/sqlstore/pageviews.go @@ -36,12 +36,27 @@ func (db *sqlstore) InsertPageviews(pageviews []*models.Pageview) error { placeholders := strings.Repeat("(?, ?, ?, ?, ?, ?, ?, ?, ?, ?),", n) placeholders = placeholders[:len(placeholders)-1] - // generate values slice - values := make([]interface{}, 0, n*10) - for i := 0; i < n; i++ { - values = append(values, pageviews[i].ID, pageviews[i].Hostname, pageviews[i].Pathname, pageviews[i].IsNewVisitor, pageviews[i].IsNewSession, pageviews[i].IsUnique, pageviews[i].IsBounce, pageviews[i].Referrer, pageviews[i].Duration, pageviews[i].Timestamp) + // init values slice with correct length + nValues := n * 10 + values := make([]interface{}, nValues) + + // overwrite nil values in slice + j := 0 + for i := range pageviews { + j = i * 10 + values[j] = pageviews[i].ID + values[j+1] = pageviews[i].Hostname + values[j+2] = pageviews[i].Pathname + values[j+3] = pageviews[i].IsNewVisitor + values[j+4] = pageviews[i].IsNewSession + values[j+5] = pageviews[i].IsUnique + values[j+6] = pageviews[i].IsBounce + values[j+7] = pageviews[i].Referrer + values[j+8] = pageviews[i].Duration + values[j+9] = pageviews[i].Timestamp } + // string together query & execute with values query := `INSERT INTO pageviews(id, hostname, pathname, is_new_visitor, is_new_session, is_unique, is_bounce, referrer, duration, timestamp) VALUES ` + placeholders query = db.Rebind(query) _, err := db.Exec(query, values...) @@ -69,7 +84,7 @@ func (db *sqlstore) UpdatePageviews(pageviews []*models.Pageview) error { return err } - for i := 0; i < len(pageviews); i++ { + for i := range pageviews { _, err = stmt.Exec(query, pageviews[i].IsBounce, pageviews[i].Duration) }