Skip to content
quarry Artifact [f92151a80c]
Login

Artifact [f92151a80c]

Artifact f92151a80cf448276dfcd9653113658e935d9cb1b1f1f7f8064ba4002aa85ce2:


package index

import (
	"fmt"
	"path/filepath"
	"testing"
	"time"
)

// Budgets from RFC 0013 §9, measured against this fixture rather than
// assumed: Activity on the tree axis under 200ms, ActivityDays cold
// under 300ms. They are not asserted — a benchmark that fails on a busy
// machine teaches people to ignore it — but a regression shows up as a
// number nobody has to hunt for.

// benchIndex builds a store the size of sqlite's: 40,000 check-ins over
// ~2,000 days by 12 people, one in ten a merge, five files each, with
// the ancestor directory rows the fold writes (~240,000 filechange
// rows in all).
func benchIndex(b *testing.B) *Index {
	b.Helper()
	ix, err := Open(filepath.Join(b.TempDir(), "index.db"))
	if err != nil {
		b.Fatal(err)
	}
	b.Cleanup(func() { ix.Close() })

	const checkins = 40000
	dirs := []string{"src", "test", "doc", "tool", "ext"}
	users := make([]string, 12)
	for i := range users {
		users[i] = fmt.Sprintf("user%02d", i)
	}
	start := time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)

	tx, err := ix.db.Begin()
	if err != nil {
		b.Fatal(err)
	}
	ci, err := tx.Prepare(`INSERT INTO checkin (hash, date, user, comment, branch)
		VALUES (?, ?, ?, '', ?)`)
	if err != nil {
		b.Fatal(err)
	}
	par, err := tx.Prepare(`INSERT INTO checkin_parent (child, parent, ord) VALUES (?, ?, ?)`)
	if err != nil {
		b.Fatal(err)
	}
	fc, err := tx.Prepare(`INSERT INTO filechange (path, checkin, date, dir) VALUES (?, ?, ?, ?)`)
	if err != nil {
		b.Fatal(err)
	}
	for i := range checkins {
		hash := fmt.Sprintf("c%06d", i)
		date := start.AddDate(0, 0, i/20).Format("2006-01-02") +
			fmt.Sprintf("T%02d:%02d:00.000", i%24, i%60)
		branch := "trunk"
		if i%7 == 0 {
			branch = "feat"
		}
		if _, err := ci.Exec(hash, date, users[i%len(users)], branch); err != nil {
			b.Fatal(err)
		}
		if i > 0 {
			if _, err := par.Exec(hash, fmt.Sprintf("c%06d", i-1), 0); err != nil {
				b.Fatal(err)
			}
			if i%10 == 0 {
				if _, err := par.Exec(hash, fmt.Sprintf("c%06d", i/2), 1); err != nil {
					b.Fatal(err)
				}
			}
		}
		seen := map[string]bool{}
		for k := range 5 {
			d := dirs[(i+k)%len(dirs)]
			if _, err := fc.Exec(fmt.Sprintf("%s/f%04d.go", d, (i*5+k)%800),
				hash, date, 0); err != nil {
				b.Fatal(err)
			}
			if !seen[d] {
				seen[d] = true
				if _, err := fc.Exec(d, hash, date, 1); err != nil {
					b.Fatal(err)
				}
			}
		}
	}
	if err := tx.Commit(); err != nil {
		b.Fatal(err)
	}
	return ix
}

func BenchmarkActivity(b *testing.B) {
	ix := benchIndex(b)
	b.ResetTimer()
	for b.Loop() {
		got, err := ix.Activity(ActivityQuery{})
		if err != nil {
			b.Fatal(err)
		}
		if len(got.Rows) == 0 || len(got.Touches) == 0 {
			b.Fatalf("empty window: %d rows %d touches", len(got.Rows), len(got.Touches))
		}
	}
}

func BenchmarkActivityDays(b *testing.B) {
	ix := benchIndex(b)
	b.ResetTimer()
	for b.Loop() {
		// Cold each time: the memo is the point of the warm path, and
		// the number that matters is what a fold makes somebody pay.
		ix.invalidateCounts()
		got, err := ix.ActivityDays("")
		if err != nil {
			b.Fatal(err)
		}
		if len(got.Days) == 0 {
			b.Fatal("no days")
		}
	}
}

func BenchmarkActivityDaysWarm(b *testing.B) {
	ix := benchIndex(b)
	if _, err := ix.ActivityDays(""); err != nil {
		b.Fatal(err)
	}
	b.ResetTimer()
	for b.Loop() {
		if _, err := ix.ActivityDays(""); err != nil {
			b.Fatal(err)
		}
	}
}