MM-21368: Optimize MapStringsToQueryParams (#13601)

- Use strings.Builder which minimizes allocations.
- Avoid fmt.Sprintf which is slower than simple string concat.

Results:

name                                      old time/op    new time/op    delta
MapStringsToQueryParams/one_item-8           512ns ± 2%     377ns ± 1%  -26.27%  (p=0.000 n=10+9)
MapStringsToQueryParams/multiple_items-8     858ns ± 5%     748ns ± 2%  -12.82%  (p=0.000 n=10+9)

name                                      old alloc/op   new alloc/op   delta
MapStringsToQueryParams/one_item-8            456B ± 0%      384B ± 0%  -15.79%  (p=0.000 n=10+9)
MapStringsToQueryParams/multiple_items-8      608B ± 0%      592B ± 0%   -2.63%  (p=0.000 n=10+10)

name                                      old allocs/op  new allocs/op  delta
MapStringsToQueryParams/one_item-8            8.00 ± 0%      6.00 ± 0%  -25.00%  (p=0.000 n=10+10)
MapStringsToQueryParams/multiple_items-8      12.0 ± 0%      12.0 ± 0%     ~     (all equal)
This commit is contained in:
Agniva De Sarker
2020-01-09 21:14:01 +05:30
committed by Christopher Speller
parent 62b57143c8
commit 2dba5dbf86
2 changed files with 20 additions and 4 deletions

View File

@@ -4,9 +4,7 @@
package sqlstore
import (
"bytes"
"database/sql"
"fmt"
"strconv"
"strings"
@@ -32,7 +30,7 @@ func sanitizeSearchTerm(term string, escapeChar string) string {
// Converts a list of strings into a list of query parameters and a named parameter map that can
// be used as part of a SQL query.
func MapStringsToQueryParams(list []string, paramPrefix string) (string, map[string]interface{}) {
keys := bytes.Buffer{}
var keys strings.Builder
params := make(map[string]interface{}, len(list))
for i, entry := range list {
if keys.Len() > 0 {
@@ -44,7 +42,7 @@ func MapStringsToQueryParams(list []string, paramPrefix string) (string, map[str
params[key] = entry
}
return fmt.Sprintf("(%v)", keys.String()), params
return "(" + keys.String() + ")", params
}
// finalizeTransaction ensures a transaction is closed after use, rolling back if not already committed.

View File

@@ -33,6 +33,24 @@ func TestMapStringsToQueryParams(t *testing.T) {
})
}
var keys string
var params map[string]interface{}
func BenchmarkMapStringsToQueryParams(b *testing.B) {
b.Run("one item", func(b *testing.B) {
input := []string{"apple"}
for i := 0; i < b.N; i++ {
keys, params = MapStringsToQueryParams(input, "Fruit")
}
})
b.Run("multiple items", func(b *testing.B) {
input := []string{"carrot", "tomato", "potato"}
for i := 0; i < b.N; i++ {
keys, params = MapStringsToQueryParams(input, "Vegetable")
}
})
}
func TestSanitizeSearchTerm(t *testing.T) {
term := "test"
result := sanitizeSearchTerm(term, "\\")