Skip to content

Commit 5d321b4

Browse files
committed
improve Set performance as #issue107 descripes
1 parent f7e751e commit 5d321b4

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
@@ -594,48 +594,96 @@ var (
594594
)
595595

596596
func createInsertComponent(keys []string, setValue []byte, comma, object bool) []byte {
597-
var buffer bytes.Buffer
598597
isIndex := string(keys[0][0]) == "["
598+
offset := 0
599+
lk := calcAllocateSpace(keys, setValue, comma, object)
600+
buffer := make([]byte, lk, lk)
599601
if comma {
600-
buffer.WriteString(",")
602+
offset += WriteToBuffer(buffer[offset:], ",")
601603
}
602604
if isIndex && !comma {
603-
buffer.WriteString("[")
605+
offset += WriteToBuffer(buffer[offset:], "[")
604606
} else {
605607
if object {
606-
buffer.WriteString("{")
608+
offset += WriteToBuffer(buffer[offset:], "{")
607609
}
608610
if !isIndex {
609-
buffer.WriteString("\"")
610-
buffer.WriteString(keys[0])
611-
buffer.WriteString("\":")
611+
offset += WriteToBuffer(buffer[offset:], "\"")
612+
offset += WriteToBuffer(buffer[offset:], keys[0])
613+
offset += WriteToBuffer(buffer[offset:], "\":")
612614
}
613615
}
614616

615617
for i := 1; i < len(keys); i++ {
616618
if string(keys[i][0]) == "[" {
617-
buffer.WriteString("[")
619+
offset += WriteToBuffer(buffer[offset:], "[")
618620
} else {
619-
buffer.WriteString("{\"")
620-
buffer.WriteString(keys[i])
621-
buffer.WriteString("\":")
621+
offset += WriteToBuffer(buffer[offset:], "{\"")
622+
offset += WriteToBuffer(buffer[offset:], keys[i])
623+
offset += WriteToBuffer(buffer[offset:], "\":")
622624
}
623625
}
624-
buffer.Write(setValue)
626+
offset += WriteToBuffer(buffer[offset:], string(setValue))
625627
for i := len(keys) - 1; i > 0; i-- {
626628
if string(keys[i][0]) == "[" {
627-
buffer.WriteString("]")
629+
offset += WriteToBuffer(buffer[offset:], "]")
628630
} else {
629-
buffer.WriteString("}")
631+
offset += WriteToBuffer(buffer[offset:], "}")
630632
}
631633
}
632634
if isIndex && !comma {
633-
buffer.WriteString("]")
635+
offset += WriteToBuffer(buffer[offset:], "]")
636+
}
637+
if object && !isIndex {
638+
offset += WriteToBuffer(buffer[offset:], "}")
639+
}
640+
return buffer
641+
}
642+
643+
func calcAllocateSpace(keys []string, setValue []byte, comma, object bool) int {
644+
isIndex := string(keys[0][0]) == "["
645+
lk := 0
646+
if comma {
647+
// ,
648+
lk += 1
649+
}
650+
if isIndex && !comma {
651+
// []
652+
lk += 2
653+
} else {
654+
if object {
655+
// {
656+
lk += 1
657+
}
658+
if !isIndex {
659+
// "keys[0]"
660+
lk += len(keys[0]) + 3
661+
}
634662
}
663+
664+
665+
lk += len(setValue)
666+
for i := 1; i < len(keys); i++ {
667+
if string(keys[i][0]) == "[" {
668+
// []
669+
lk += 2
670+
} else {
671+
// {"keys[i]":setValue}
672+
lk += len(keys[i]) + 5
673+
}
674+
}
675+
635676
if object && !isIndex {
636-
buffer.WriteString("}")
677+
// }
678+
lk += 1
637679
}
638-
return buffer.Bytes()
680+
681+
return lk
682+
}
683+
684+
func WriteToBuffer(buffer []byte, str string) int {
685+
copy(buffer, str)
686+
return len(str)
639687
}
640688

641689
/*

0 commit comments

Comments
 (0)