Skip to content

Commit 2c02b22

Browse files
author
Dan Purpura
committed
Use bytes.Buffer for string concatenation to improve performance
1 parent e7c9711 commit 2c02b22

File tree

1 file changed

+65
-31
lines changed

1 file changed

+65
-31
lines changed

serialize.go

Lines changed: 65 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package php_serialize
22

33
import (
4+
"bytes"
45
"fmt"
56
"strconv"
67
)
@@ -25,7 +26,7 @@ func (self *Serializer) SetSerializedEncodeFunc(f SerializedEncodeFunc) {
2526
}
2627

2728
func (self *Serializer) Encode(v PhpValue) (string, error) {
28-
var value string
29+
var value bytes.Buffer
2930

3031
switch t := v.(type) {
3132
default:
@@ -46,22 +47,30 @@ func (self *Serializer) Encode(v PhpValue) (string, error) {
4647
value = self.encodeSerialized(v)
4748
}
4849

49-
return value, self.lastErr
50+
return value.String(), self.lastErr
5051
}
5152

52-
func (self *Serializer) encodeNull() string {
53-
return string(TOKEN_NULL) + string(SEPARATOR_VALUES)
53+
func (self *Serializer) encodeNull() (buffer bytes.Buffer) {
54+
buffer.WriteRune(TOKEN_NULL)
55+
buffer.WriteRune(SEPARATOR_VALUES)
56+
return
5457
}
5558

56-
func (self *Serializer) encodeBool(v PhpValue) string {
57-
val := "0"
59+
func (self *Serializer) encodeBool(v PhpValue) (buffer bytes.Buffer) {
60+
buffer.WriteRune(TOKEN_BOOL)
61+
buffer.WriteRune(SEPARATOR_VALUE_TYPE)
62+
5863
if bVal, ok := v.(bool); ok && bVal == true {
59-
val = "1"
64+
buffer.WriteString("1")
65+
} else {
66+
buffer.WriteString("0")
6067
}
61-
return string(TOKEN_BOOL) + string(SEPARATOR_VALUE_TYPE) + val + string(SEPARATOR_VALUES)
68+
69+
buffer.WriteRune(SEPARATOR_VALUES)
70+
return
6271
}
6372

64-
func (self *Serializer) encodeNumber(v PhpValue) (res string) {
73+
func (self *Serializer) encodeNumber(v PhpValue) (buffer bytes.Buffer) {
6574
var val string
6675

6776
isFloat := false
@@ -111,74 +120,97 @@ func (self *Serializer) encodeNumber(v PhpValue) (res string) {
111120
}
112121

113122
if isFloat {
114-
res = string(TOKEN_FLOAT)
123+
buffer.WriteRune(TOKEN_FLOAT)
115124
} else {
116-
res = string(TOKEN_INT)
125+
buffer.WriteRune(TOKEN_INT)
117126
}
118127

119-
res += string(SEPARATOR_VALUE_TYPE) + val + string(SEPARATOR_VALUES)
128+
buffer.WriteRune(SEPARATOR_VALUE_TYPE)
129+
buffer.WriteString(val)
130+
buffer.WriteRune(SEPARATOR_VALUES)
131+
120132
return
121133
}
122134

123-
func (self *Serializer) encodeString(v PhpValue, left, right rune, isFinal bool) (res string) {
135+
func (self *Serializer) encodeString(v PhpValue, left, right rune, isFinal bool) (buffer bytes.Buffer) {
124136
val, _ := v.(string)
125137

126138
if isFinal {
127-
res = string(TOKEN_STRING)
139+
buffer.WriteRune(TOKEN_STRING)
128140
}
129-
res += self.prepareLen(len(val)) + string(left) + val + string(right)
141+
142+
buffer.WriteString(self.prepareLen(len(val)))
143+
buffer.WriteRune(left)
144+
buffer.WriteString(val)
145+
buffer.WriteRune(right)
146+
130147
if isFinal {
131-
res += string(SEPARATOR_VALUES)
148+
buffer.WriteRune(SEPARATOR_VALUES)
132149
}
150+
133151
return
134152
}
135153

136-
func (self *Serializer) encodeArray(v PhpValue, isFinal bool) (res string) {
154+
func (self *Serializer) encodeArray(v PhpValue, isFinal bool) (buffer bytes.Buffer) {
137155
var (
138-
arrLen int
139-
data, s string
156+
arrLen int
157+
s string
140158
)
141159

142160
if isFinal {
143-
res = string(TOKEN_ARRAY)
161+
buffer.WriteRune(TOKEN_ARRAY)
144162
}
145163

146164
switch v.(type) {
147165
case PhpArray:
148166
arrVal, _ := v.(PhpArray)
149167
arrLen = len(arrVal)
168+
169+
buffer.WriteString(self.prepareLen(arrLen))
170+
buffer.WriteRune(DELIMITER_OBJECT_LEFT)
171+
150172
for k, v := range arrVal {
151173
s, _ = self.Encode(k)
152-
data += s
174+
buffer.WriteString(s)
153175
s, _ = self.Encode(v)
154-
data += s
176+
buffer.WriteString(s)
155177
}
156178

157179
case map[PhpValue]PhpValue:
158180
arrVal, _ := v.(map[PhpValue]PhpValue)
159181
arrLen = len(arrVal)
182+
183+
buffer.WriteString(self.prepareLen(arrLen))
184+
buffer.WriteRune(DELIMITER_OBJECT_LEFT)
185+
160186
for k, v := range arrVal {
161187
s, _ = self.Encode(k)
162-
data += s
188+
buffer.WriteString(s)
163189
s, _ = self.Encode(v)
164-
data += s
190+
buffer.WriteString(s)
165191
}
166192
}
167193

168-
res += self.prepareLen(arrLen) + string(DELIMITER_OBJECT_LEFT) + data + string(DELIMITER_OBJECT_RIGHT)
194+
buffer.WriteRune(DELIMITER_OBJECT_RIGHT)
195+
169196
return
170197
}
171198

172-
func (self *Serializer) encodeObject(v PhpValue) string {
199+
func (self *Serializer) encodeObject(v PhpValue) (buffer bytes.Buffer) {
173200
obj, _ := v.(*PhpObject)
174-
return string(TOKEN_OBJECT) + self.prepareClassName(obj.className) + self.encodeArray(obj.members, false)
201+
buffer.WriteRune(TOKEN_OBJECT)
202+
buffer.WriteString(self.prepareClassName(obj.className))
203+
encoded := self.encodeArray(obj.members, false)
204+
buffer.WriteString(encoded.String())
205+
return
175206
}
176207

177-
func (self *Serializer) encodeSerialized(v PhpValue) (res string) {
208+
func (self *Serializer) encodeSerialized(v PhpValue) (buffer bytes.Buffer) {
178209
var serialized string
179210

180211
obj, _ := v.(*PhpObjectSerialized)
181-
res = string(TOKEN_OBJECT_SERIALIZED) + self.prepareClassName(obj.className)
212+
buffer.WriteRune(TOKEN_OBJECT_SERIALIZED)
213+
buffer.WriteString(self.prepareClassName(obj.className))
182214

183215
if self.encodeFunc == nil {
184216
serialized = obj.GetData()
@@ -189,7 +221,8 @@ func (self *Serializer) encodeSerialized(v PhpValue) (res string) {
189221
}
190222
}
191223

192-
res += self.encodeString(serialized, DELIMITER_OBJECT_LEFT, DELIMITER_OBJECT_RIGHT, false)
224+
encoded := self.encodeString(serialized, DELIMITER_OBJECT_LEFT, DELIMITER_OBJECT_RIGHT, false)
225+
buffer.WriteString(encoded.String())
193226
return
194227
}
195228

@@ -198,7 +231,8 @@ func (self *Serializer) prepareLen(l int) string {
198231
}
199232

200233
func (self *Serializer) prepareClassName(name string) string {
201-
return self.encodeString(name, DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, false)
234+
encoded := self.encodeString(name, DELIMITER_STRING_LEFT, DELIMITER_STRING_RIGHT, false)
235+
return encoded.String()
202236
}
203237

204238
func (self *Serializer) saveError(err error) {

0 commit comments

Comments
 (0)