Skip to content

Commit b2d260f

Browse files
committed
reduce serialize allocations
Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com>
1 parent 7aa56e7 commit b2d260f

File tree

2 files changed

+33
-26
lines changed

2 files changed

+33
-26
lines changed

fieldpath/serialize-pe.go

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -54,31 +54,28 @@ var (
5454

5555
// DeserializePathElement parses a serialized path element
5656
func DeserializePathElement(s string) (PathElement, error) {
57-
b := []byte(s)
58-
if len(b) < 2 {
57+
if len(s) < 2 {
5958
return PathElement{}, errors.New("key must be 2 characters long")
6059
}
61-
typeSep0, typeSep1, b := b[0], b[1], b[2:]
60+
typeSep0, typeSep1, rest := s[0], s[1], s[2:]
6261
if typeSep1 != peSeparator {
6362
return PathElement{}, fmt.Errorf("missing colon: %v", s)
6463
}
6564
switch typeSep0 {
6665
case peFieldSepBytes[0]:
67-
// Slice s rather than convert b, to save on
68-
// allocations.
6966
str := s[2:]
7067
return PathElement{
7168
FieldName: &str,
7269
}, nil
7370
case peValueSepBytes[0]:
74-
v, err := value.FromJSON(b)
71+
v, err := value.FromJSON([]byte(rest))
7572
if err != nil {
7673
return PathElement{}, err
7774
}
7875
return PathElement{Value: &v}, nil
7976
case peKeySepBytes[0]:
8077
var fields value.FieldList
81-
if err := json.Unmarshal(b, &fields); err != nil {
78+
if err := json.Unmarshal([]byte(rest), &fields); err != nil {
8279
return PathElement{}, err
8380
}
8481
return PathElement{Key: &fields}, nil
@@ -97,41 +94,52 @@ func DeserializePathElement(s string) (PathElement, error) {
9794

9895
// SerializePathElement serializes a path element
9996
func SerializePathElement(pe PathElement) (string, error) {
100-
builder := bytes.Buffer{}
101-
if err := serializePathElementBuilder(pe, &builder); err != nil {
97+
serializer := pathElementSerializer{}
98+
if err := serializer.serialize(pe); err != nil {
10299
return "", err
103100
}
104-
return builder.String(), nil
101+
return serializer.builder.String(), nil
105102
}
106103

107-
func serializePathElementBuilder(pe PathElement, builder *bytes.Buffer) error {
104+
type pathElementSerializer struct {
105+
builder bytes.Buffer
106+
fastValue value.MarshalValue
107+
}
108+
109+
func (pes *pathElementSerializer) reset() {
110+
pes.builder.Reset()
111+
pes.fastValue.Value = nil
112+
}
113+
114+
func (pes *pathElementSerializer) serialize(pe PathElement) error {
108115
switch {
109116
case pe.FieldName != nil:
110-
if _, err := builder.Write(peFieldSepBytes); err != nil {
117+
if _, err := pes.builder.Write(peFieldSepBytes); err != nil {
111118
return err
112119
}
113-
if _, err := builder.WriteString(*pe.FieldName); err != nil {
120+
if _, err := pes.builder.WriteString(*pe.FieldName); err != nil {
114121
return err
115122
}
116123
case pe.Key != nil:
117-
if _, err := builder.Write(peKeySepBytes); err != nil {
124+
if _, err := pes.builder.Write(peKeySepBytes); err != nil {
118125
return err
119126
}
120-
if err := json.MarshalWrite(builder, pe.Key, json.Deterministic(true)); err != nil {
127+
if err := json.MarshalWrite(&pes.builder, pe.Key, json.Deterministic(true)); err != nil {
121128
return err
122129
}
123130
case pe.Value != nil:
124-
if _, err := builder.Write(peValueSepBytes); err != nil {
131+
if _, err := pes.builder.Write(peValueSepBytes); err != nil {
125132
return err
126133
}
127-
if err := json.MarshalWrite(builder, value.MarshalValue{Value: pe.Value}, json.Deterministic(true)); err != nil {
134+
pes.fastValue.Value = pe.Value
135+
if err := json.MarshalWrite(&pes.builder, &pes.fastValue, json.Deterministic(true)); err != nil {
128136
return err
129137
}
130138
case pe.Index != nil:
131-
if _, err := builder.Write(peIndexSepBytes); err != nil {
139+
if _, err := pes.builder.Write(peIndexSepBytes); err != nil {
132140
return err
133141
}
134-
if _, err := builder.WriteString(strconv.Itoa(*pe.Index)); err != nil {
142+
if _, err := pes.builder.WriteString(strconv.Itoa(*pe.Index)); err != nil {
135143
return err
136144
}
137145
default:

fieldpath/serialize.go

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package fieldpath
1818

1919
import (
20-
"bytes"
2120
"fmt"
2221
"io"
2322
"sort"
@@ -37,22 +36,22 @@ func (s *Set) ToJSONStream(w io.Writer) error {
3736

3837
var pool = sync.Pool{
3938
New: func() any {
40-
return &bytes.Buffer{}
39+
return &pathElementSerializer{}
4140
},
4241
}
4342

4443
func writePathKey(enc *jsontext.Encoder, pe PathElement) error {
45-
builder := pool.Get().(*bytes.Buffer)
44+
serializer := pool.Get().(*pathElementSerializer)
4645
defer func() {
47-
builder.Reset()
48-
pool.Put(builder)
46+
serializer.reset()
47+
pool.Put(serializer)
4948
}()
5049

51-
if err := serializePathElementBuilder(pe, builder); err != nil {
50+
if err := serializer.serialize(pe); err != nil {
5251
return err
5352
}
5453

55-
if err := enc.WriteToken(jsontext.String(builder.String())); err != nil {
54+
if err := enc.WriteToken(jsontext.String(serializer.builder.String())); err != nil {
5655
return err
5756
}
5857
return nil

0 commit comments

Comments
 (0)