Skip to content

Commit e015c37

Browse files
authored
Merge pull request #196 from AllenX2018/fix-issue-107
improve Set performance as #issue107 descripes
2 parents 9b2f299 + 5d321b4 commit e015c37

File tree

2 files changed

+85
-17
lines changed

2 files changed

+85
-17
lines changed

benchmark/benchmark_set_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package benchmark
2+
3+
import (
4+
"github.com/buger/jsonparser"
5+
"strconv"
6+
"testing"
7+
)
8+
9+
func BenchmarkSetLarge(b *testing.B) {
10+
b.ReportAllocs()
11+
12+
keyPath := make([]string, 20000)
13+
for i := range keyPath {
14+
keyPath[i] = "keyPath" + strconv.Itoa(i)
15+
}
16+
b.ResetTimer()
17+
for i := 0; i < b.N; i++ {
18+
_, _ = jsonparser.Set(largeFixture, largeFixture, keyPath...)
19+
}
20+
}

parser.go

Lines changed: 65 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -591,48 +591,96 @@ var (
591591
)
592592

593593
func createInsertComponent(keys []string, setValue []byte, comma, object bool) []byte {
594-
var buffer bytes.Buffer
595594
isIndex := string(keys[0][0]) == "["
595+
offset := 0
596+
lk := calcAllocateSpace(keys, setValue, comma, object)
597+
buffer := make([]byte, lk, lk)
596598
if comma {
597-
buffer.WriteString(",")
599+
offset += WriteToBuffer(buffer[offset:], ",")
598600
}
599601
if isIndex && !comma {
600-
buffer.WriteString("[")
602+
offset += WriteToBuffer(buffer[offset:], "[")
601603
} else {
602604
if object {
603-
buffer.WriteString("{")
605+
offset += WriteToBuffer(buffer[offset:], "{")
604606
}
605607
if !isIndex {
606-
buffer.WriteString("\"")
607-
buffer.WriteString(keys[0])
608-
buffer.WriteString("\":")
608+
offset += WriteToBuffer(buffer[offset:], "\"")
609+
offset += WriteToBuffer(buffer[offset:], keys[0])
610+
offset += WriteToBuffer(buffer[offset:], "\":")
609611
}
610612
}
611613

612614
for i := 1; i < len(keys); i++ {
613615
if string(keys[i][0]) == "[" {
614-
buffer.WriteString("[")
616+
offset += WriteToBuffer(buffer[offset:], "[")
615617
} else {
616-
buffer.WriteString("{\"")
617-
buffer.WriteString(keys[i])
618-
buffer.WriteString("\":")
618+
offset += WriteToBuffer(buffer[offset:], "{\"")
619+
offset += WriteToBuffer(buffer[offset:], keys[i])
620+
offset += WriteToBuffer(buffer[offset:], "\":")
619621
}
620622
}
621-
buffer.Write(setValue)
623+
offset += WriteToBuffer(buffer[offset:], string(setValue))
622624
for i := len(keys) - 1; i > 0; i-- {
623625
if string(keys[i][0]) == "[" {
624-
buffer.WriteString("]")
626+
offset += WriteToBuffer(buffer[offset:], "]")
625627
} else {
626-
buffer.WriteString("}")
628+
offset += WriteToBuffer(buffer[offset:], "}")
627629
}
628630
}
629631
if isIndex && !comma {
630-
buffer.WriteString("]")
632+
offset += WriteToBuffer(buffer[offset:], "]")
633+
}
634+
if object && !isIndex {
635+
offset += WriteToBuffer(buffer[offset:], "}")
636+
}
637+
return buffer
638+
}
639+
640+
func calcAllocateSpace(keys []string, setValue []byte, comma, object bool) int {
641+
isIndex := string(keys[0][0]) == "["
642+
lk := 0
643+
if comma {
644+
// ,
645+
lk += 1
646+
}
647+
if isIndex && !comma {
648+
// []
649+
lk += 2
650+
} else {
651+
if object {
652+
// {
653+
lk += 1
654+
}
655+
if !isIndex {
656+
// "keys[0]"
657+
lk += len(keys[0]) + 3
658+
}
631659
}
660+
661+
662+
lk += len(setValue)
663+
for i := 1; i < len(keys); i++ {
664+
if string(keys[i][0]) == "[" {
665+
// []
666+
lk += 2
667+
} else {
668+
// {"keys[i]":setValue}
669+
lk += len(keys[i]) + 5
670+
}
671+
}
672+
632673
if object && !isIndex {
633-
buffer.WriteString("}")
674+
// }
675+
lk += 1
634676
}
635-
return buffer.Bytes()
677+
678+
return lk
679+
}
680+
681+
func WriteToBuffer(buffer []byte, str string) int {
682+
copy(buffer, str)
683+
return len(str)
636684
}
637685

638686
/*

0 commit comments

Comments
 (0)