Skip to content

Commit

Permalink
Optimize In by specializing for concrete slice types
Browse files Browse the repository at this point in the history
  • Loading branch information
nussjustin committed Feb 17, 2017
1 parent f980a91 commit 5608f0d
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
28 changes: 24 additions & 4 deletions bind.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ func In(query string, args ...interface{}) (string, []interface{}, error) {
}

newArgs := make([]interface{}, 0, flatArgsCount)
buf := bytes.NewBuffer(make([]byte, 0, len(query)+len(", ?")*flatArgsCount))

var arg, offset int
var buf bytes.Buffer

for i := strings.IndexByte(query[offset:], '?'); i != -1; i = strings.IndexByte(query[offset:], '?') {
if arg >= len(meta) {
Expand All @@ -163,13 +163,12 @@ func In(query string, args ...interface{}) (string, []interface{}, error) {
// write everything up to and including our ? character
buf.WriteString(query[:offset+i+1])

newArgs = append(newArgs, argMeta.v.Index(0).Interface())

for si := 1; si < argMeta.length; si++ {
buf.WriteString(", ?")
newArgs = append(newArgs, argMeta.v.Index(si).Interface())
}

newArgs = appendReflectSlice(newArgs, argMeta.v, argMeta.length)

// slice the query and reset the offset. this avoids some bookkeeping for
// the write after the loop
query = query[offset+i+1:]
Expand All @@ -184,3 +183,24 @@ func In(query string, args ...interface{}) (string, []interface{}, error) {

return buf.String(), newArgs, nil
}

func appendReflectSlice(args []interface{}, v reflect.Value, vlen int) []interface{} {
switch val := v.Interface().(type) {
case []interface{}:
args = append(args, val...)
case []int:
for i := range val {
args = append(args, val[i])
}
case []string:
for i := range val {
args = append(args, val[i])
}
default:
for si := 0; si < vlen; si++ {
args = append(args, v.Index(si).Interface())
}
}

return args
}
30 changes: 30 additions & 0 deletions sqlx_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1726,6 +1726,36 @@ func BenchmarkIn(b *testing.B) {
}
}

func BenchmarkIn1k(b *testing.B) {
q := `SELECT * FROM foo WHERE x = ? AND v in (?) AND y = ?`

var vals [1000]interface{}

for i := 0; i < b.N; i++ {
_, _, _ = In(q, []interface{}{"foo", vals[:], "bar"}...)
}
}

func BenchmarkIn1kInt(b *testing.B) {
q := `SELECT * FROM foo WHERE x = ? AND v in (?) AND y = ?`

var vals [1000]int

for i := 0; i < b.N; i++ {
_, _, _ = In(q, []interface{}{"foo", vals[:], "bar"}...)
}
}

func BenchmarkIn1kString(b *testing.B) {
q := `SELECT * FROM foo WHERE x = ? AND v in (?) AND y = ?`

var vals [1000]string

for i := 0; i < b.N; i++ {
_, _, _ = In(q, []interface{}{"foo", vals[:], "bar"}...)
}
}

func BenchmarkRebind(b *testing.B) {
b.StopTimer()
q1 := `INSERT INTO foo (a, b, c, d, e, f, g, h, i) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`
Expand Down

0 comments on commit 5608f0d

Please sign in to comment.