Skip to content

Commit f9bd00a

Browse files
19118605381911860538
andauthored
perf(context): optimize getMapFromFormData performance (#4339)
Co-authored-by: 1911860538 <alxps1911@gmail.com>
1 parent 28172fa commit f9bd00a

2 files changed

Lines changed: 99 additions & 5 deletions

File tree

context.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -654,14 +654,23 @@ func (c *Context) GetPostFormMap(key string) (map[string]string, bool) {
654654
func getMapFromFormData(m map[string][]string, key string) (map[string]string, bool) {
655655
d := make(map[string]string)
656656
found := false
657+
keyLen := len(key)
658+
657659
for k, v := range m {
658-
if i := strings.IndexByte(k, '['); i >= 1 && k[0:i] == key {
659-
if j := strings.IndexByte(k[i+1:], ']'); j >= 1 {
660-
found = true
661-
d[k[i+1:][:j]] = v[0]
662-
}
660+
if len(k) < keyLen+3 { // key + "[" + at least one char + "]"
661+
continue
662+
}
663+
664+
if k[:keyLen] != key || k[keyLen] != '[' {
665+
continue
666+
}
667+
668+
if j := strings.IndexByte(k[keyLen+1:], ']'); j > 0 {
669+
found = true
670+
d[k[keyLen+1:keyLen+1+j]] = v[0]
663671
}
664672
}
673+
665674
return d, found
666675
}
667676

context_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3554,3 +3554,88 @@ func TestGetMapFromFormData(t *testing.T) {
35543554
})
35553555
}
35563556
}
3557+
3558+
func BenchmarkGetMapFromFormData(b *testing.B) {
3559+
// Test case 1: Small dataset with bracket notation
3560+
smallData := map[string][]string{
3561+
"ids[a]": {"hi"},
3562+
"ids[b]": {"3.14"},
3563+
"names[a]": {"mike"},
3564+
"names[b]": {"maria"},
3565+
}
3566+
3567+
// Test case 2: Medium dataset with mixed data
3568+
mediumData := map[string][]string{
3569+
"ids[a]": {"hi"},
3570+
"ids[b]": {"3.14"},
3571+
"ids[c]": {"test"},
3572+
"ids[d]": {"value"},
3573+
"names[a]": {"mike"},
3574+
"names[b]": {"maria"},
3575+
"names[c]": {"john"},
3576+
"names[d]": {"jane"},
3577+
"other[key1]": {"value1"},
3578+
"other[key2]": {"value2"},
3579+
"simple": {"data"},
3580+
"another": {"info"},
3581+
}
3582+
3583+
// Test case 3: Large dataset with many bracket keys
3584+
largeData := make(map[string][]string)
3585+
for i := 0; i < 100; i++ {
3586+
key := fmt.Sprintf("ids[%d]", i)
3587+
largeData[key] = []string{fmt.Sprintf("value%d", i)}
3588+
}
3589+
for i := 0; i < 50; i++ {
3590+
key := fmt.Sprintf("names[%d]", i)
3591+
largeData[key] = []string{fmt.Sprintf("name%d", i)}
3592+
}
3593+
for i := 0; i < 25; i++ {
3594+
key := fmt.Sprintf("other[key%d]", i)
3595+
largeData[key] = []string{fmt.Sprintf("other%d", i)}
3596+
}
3597+
3598+
// Test case 4: Dataset with many non-matching keys (worst case)
3599+
worstCaseData := make(map[string][]string)
3600+
for i := 0; i < 100; i++ {
3601+
key := fmt.Sprintf("nonmatching%d", i)
3602+
worstCaseData[key] = []string{fmt.Sprintf("value%d", i)}
3603+
}
3604+
worstCaseData["ids[a]"] = []string{"hi"}
3605+
worstCaseData["ids[b]"] = []string{"3.14"}
3606+
3607+
// Test case 5: Dataset with short keys (best case for early exit)
3608+
shortKeysData := map[string][]string{
3609+
"a": {"value1"},
3610+
"b": {"value2"},
3611+
"ids[a]": {"hi"},
3612+
"ids[b]": {"3.14"},
3613+
}
3614+
3615+
benchmarks := []struct {
3616+
name string
3617+
data map[string][]string
3618+
key string
3619+
}{
3620+
{"Small_Bracket", smallData, "ids"},
3621+
{"Small_Names", smallData, "names"},
3622+
{"Medium_Bracket", mediumData, "ids"},
3623+
{"Medium_Names", mediumData, "names"},
3624+
{"Medium_Other", mediumData, "other"},
3625+
{"Large_Bracket", largeData, "ids"},
3626+
{"Large_Names", largeData, "names"},
3627+
{"Large_Other", largeData, "other"},
3628+
{"WorstCase_Bracket", worstCaseData, "ids"},
3629+
{"ShortKeys_Bracket", shortKeysData, "ids"},
3630+
{"Empty_Key", smallData, "notfound"},
3631+
}
3632+
3633+
for _, bm := range benchmarks {
3634+
b.Run(bm.name, func(b *testing.B) {
3635+
b.ReportAllocs()
3636+
for i := 0; i < b.N; i++ {
3637+
_, _ = getMapFromFormData(bm.data, bm.key)
3638+
}
3639+
})
3640+
}
3641+
}

0 commit comments

Comments
 (0)