aboutsummaryrefslogtreecommitdiff
path: root/all_test.go
diff options
context:
space:
mode:
authorJan Mercl <0xjnml@gmail.com>2017-04-24 18:34:39 +0200
committerJan Mercl <0xjnml@gmail.com>2017-04-24 18:34:39 +0200
commitb1f34f398bbe81c2a8122806aedf0a6a003df369 (patch)
tree7b30276965b6652239cd4693f1560cbb77572161 /all_test.go
parent1769e4aeff84d8b46d0d24d045a9ecdd6b2e7b77 (diff)
Add simple benchmarks, enable using the new profiling API.
Diffstat (limited to 'all_test.go')
-rw-r--r--all_test.go258
1 files changed, 257 insertions, 1 deletions
diff --git a/all_test.go b/all_test.go
index 27461e8..ba74ff4 100644
--- a/all_test.go
+++ b/all_test.go
@@ -7,15 +7,20 @@ package sqlite
import (
"bytes"
"database/sql"
+ "flag"
"fmt"
+ "io"
"io/ioutil"
"os"
"path"
"path/filepath"
"runtime"
+ "sort"
"strings"
"testing"
"time"
+
+ "github.com/cznic/virtual"
)
func caller(s string, va ...interface{}) {
@@ -56,7 +61,15 @@ func init() {
// ============================================================================
-func tempDB(t *testing.T) (string, *sql.DB) {
+var (
+ // -tags virtual.profile
+ profileFunctions = flag.Bool("profile_functions", false, "")
+ profileInstructions = flag.Bool("profile_instructions", false, "")
+ profileLines = flag.Bool("profile_lines", false, "")
+ profileRate = flag.Int("profile_rate", 1000, "")
+)
+
+func tempDB(t testing.TB) (string, *sql.DB) {
dir, err := ioutil.TempDir("", "sqlite-test-")
if err != nil {
t.Fatal(err)
@@ -73,6 +86,7 @@ func tempDB(t *testing.T) (string, *sql.DB) {
func TestScalar(t *testing.T) {
dir, db := tempDB(t)
+
defer func() {
db.Close()
os.RemoveAll(dir)
@@ -140,6 +154,7 @@ func TestScalar(t *testing.T) {
func TestBlob(t *testing.T) {
dir, db := tempDB(t)
+
defer func() {
db.Close()
os.RemoveAll(dir)
@@ -188,3 +203,244 @@ func TestBlob(t *testing.T) {
t.Fatal(g, e)
}
}
+
+func profile(t testing.TB, d time.Duration, w io.Writer, format string, arg ...interface{}) {
+ rate := vm.ProfileRate
+ if rate == 0 {
+ rate = 1
+ }
+ if len(vm.ProfileFunctions) != 0 {
+ fmt.Fprintf(w, format, arg...)
+ type u struct {
+ virtual.PCInfo
+ n int
+ }
+ var s int64
+ var a []u
+ var wi int
+ for k, v := range vm.ProfileFunctions {
+ a = append(a, u{k, v})
+ s += int64(v)
+ if n := len(k.Name.String()); n > wi {
+ wi = n
+ }
+ }
+ sort.Slice(a, func(i, j int) bool {
+ if a[i].n < a[j].n {
+ return true
+ }
+
+ if a[i].n > a[j].n {
+ return false
+ }
+
+ return a[i].Name < a[j].Name
+ })
+ fmt.Fprintf(w, "---- Profile functions, %.3f MIPS\n", float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d))
+ var c int64
+ for i := len(a) - 1; i >= 0; i-- {
+ c += int64(a[i].n)
+ fmt.Fprintf(
+ w,
+ "%*v\t%10v%10.2f%%%10.2f%%\n",
+ -wi, a[i].Name, a[i].n,
+ 100*float64(a[i].n)/float64(s),
+ 100*float64(c)/float64(s),
+ )
+ }
+ }
+ if len(vm.ProfileLines) != 0 {
+ fmt.Fprintf(w, format, arg...)
+ type u struct {
+ virtual.PCInfo
+ n int
+ }
+ var s int64
+ var a []u
+ for k, v := range vm.ProfileLines {
+ a = append(a, u{k, v})
+ s += int64(v)
+ }
+ sort.Slice(a, func(i, j int) bool {
+ if a[i].n < a[j].n {
+ return true
+ }
+
+ if a[i].n > a[j].n {
+ return false
+ }
+
+ if a[i].Name < a[j].Name {
+ return true
+ }
+
+ if a[i].Name > a[j].Name {
+ return false
+ }
+
+ return a[i].Line < a[j].Line
+ })
+ fmt.Fprintf(w, "---- Profile lines, %.3f MIPS\n", float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d))
+ var c int64
+ for i := len(a) - 1; i >= 0; i-- {
+ c += int64(a[i].n)
+ fmt.Fprintf(
+ w,
+ "%v:%v:\t%10v%10.2f%%%10.2f%%\n",
+ a[i].Name, a[i].Line, a[i].n,
+ 100*float64(a[i].n)/float64(s),
+ 100*float64(c)/float64(s),
+ )
+ }
+ }
+ if len(vm.ProfileInstructions) != 0 {
+ fmt.Fprintf(w, format, arg...)
+ type u struct {
+ virtual.Opcode
+ n int
+ }
+ var s int64
+ var a []u
+ var wi int
+ for k, v := range vm.ProfileInstructions {
+ a = append(a, u{k, v})
+ s += int64(v)
+ if n := len(k.String()); n > wi {
+ wi = n
+ }
+ }
+ sort.Slice(a, func(i, j int) bool {
+ if a[i].n < a[j].n {
+ return true
+ }
+
+ if a[i].n > a[j].n {
+ return false
+ }
+
+ return a[i].Opcode < a[j].Opcode
+ })
+ fmt.Fprintf(w, "---- Profile instructions, %.3f MIPS\n", float64(s)/1e6*float64(rate)*float64(time.Second)/float64(d))
+ var c int64
+ for i := len(a) - 1; i >= 0; i-- {
+ c += int64(a[i].n)
+ fmt.Fprintf(
+ w,
+ "%*s%10v%10.2f%%\t%10.2f%%\n",
+ -wi, a[i].Opcode, a[i].n,
+ 100*float64(a[i].n)/float64(s),
+ 100*float64(c)/float64(s),
+ )
+ }
+ }
+}
+
+func BenchmarkInsertMemory(b *testing.B) {
+ db, err := sql.Open(driverName, "file::memory:")
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ defer func() {
+ db.Close()
+ }()
+
+ if _, err := db.Exec(`
+ create table t(i int);
+ begin;
+ `); err != nil {
+ b.Fatal(err)
+ }
+
+ s, err := db.Prepare("insert into t values(?)")
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ if *profileFunctions {
+ vm.ProfileFunctions = map[virtual.PCInfo]int{}
+ }
+ if *profileLines {
+ vm.ProfileLines = map[virtual.PCInfo]int{}
+ }
+ if *profileInstructions {
+ vm.ProfileInstructions = map[virtual.Opcode]int{}
+ }
+ vm.ProfileRate = int(*profileRate)
+ t0 := time.Now()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ if _, err := s.Exec(int64(i)); err != nil {
+ b.Fatal(err)
+ }
+ }
+ b.StopTimer()
+ d := time.Since(t0)
+ if _, err := db.Exec(`commit;`); err != nil {
+ b.Fatal(err)
+ }
+
+ profile(b, d, os.Stderr, "==== BenchmarkInsertMemory b.N %v\n", b.N)
+}
+
+func BenchmarkNextMemory(b *testing.B) {
+ db, err := sql.Open(driverName, "file::memory:")
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ defer func() {
+ db.Close()
+ }()
+
+ if _, err := db.Exec(`
+ create table t(i int);
+ begin;
+ `); err != nil {
+ b.Fatal(err)
+ }
+
+ s, err := db.Prepare("insert into t values(?)")
+ if err != nil {
+ b.Fatal(err)
+ }
+
+ defer s.Close()
+
+ for i := 0; i < b.N; i++ {
+ if _, err := s.Exec(int64(i)); err != nil {
+ b.Fatal(err)
+ }
+ }
+ if _, err := db.Exec("commit"); err != nil {
+ b.Fatal(err)
+ }
+
+ r, err := db.Query("select * from t")
+ if err != nil {
+
+ }
+
+ defer r.Close()
+
+ if *profileFunctions {
+ vm.ProfileFunctions = map[virtual.PCInfo]int{}
+ }
+ if *profileLines {
+ vm.ProfileLines = map[virtual.PCInfo]int{}
+ }
+ if *profileInstructions {
+ vm.ProfileInstructions = map[virtual.Opcode]int{}
+ }
+ vm.ProfileRate = int(*profileRate)
+ t0 := time.Now()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ if !r.Next() {
+ b.Fatal(err)
+ }
+ }
+ b.StopTimer()
+ d := time.Since(t0)
+ profile(b, d, os.Stderr, "==== BenchmarkNextMemory b.N %v\n", b.N)
+}