Skip to content

Commit adf8269

Browse files
committedMar 6, 2024
Optimize unmarshal type handling
Dispatch type as a byte, instead of allocating a string Before ''' 14433 ns/op 2576 B/op 108 allocs/op ''' After ''' 13616 ns/op 2512 B/op 83 allocs/op '''
1 parent 57a58bf commit adf8269

File tree

3 files changed

+92
-110
lines changed

3 files changed

+92
-110
lines changed
 

Diff for: ‎base_lexer.go

+9-27
Original file line numberDiff line numberDiff line change
@@ -178,45 +178,27 @@ func (l *baseLexer) readLine() (string, error) {
178178
}
179179
}
180180

181-
func (l *baseLexer) readString(until byte) (string, error) {
182-
start := l.pos
181+
func (l *baseLexer) readType() (byte, error) {
183182
for {
184-
ch, err := l.readByte()
183+
firstByte, err := l.readByte()
185184
if err != nil {
186-
return "", err
187-
}
188-
if ch == until {
189-
return string(l.value[start:l.pos]), nil
185+
return 0, err
190186
}
191-
}
192-
}
193187

194-
func (l *baseLexer) readType() (string, error) {
195-
for {
196-
b, err := l.readByte()
197-
if err != nil {
198-
return "", err
199-
}
200-
201-
if isNewline(b) {
188+
if isNewline(firstByte) {
202189
continue
203190
}
204191

205-
err = l.unreadByte()
206-
if err != nil {
207-
return "", err
208-
}
209-
210-
key, err := l.readString('=')
192+
secondByte, err := l.readByte()
211193
if err != nil {
212-
return key, err
194+
return 0, err
213195
}
214196

215-
if len(key) == 2 {
216-
return key, nil
197+
if secondByte != '=' {
198+
return firstByte, l.syntaxError()
217199
}
218200

219-
return key, l.syntaxError()
201+
return firstByte, nil
220202
}
221203
}
222204

Diff for: ‎unmarshal.go

+81-81
Original file line numberDiff line numberDiff line change
@@ -114,260 +114,260 @@ func (s *SessionDescription) Unmarshal(value []byte) error {
114114
}
115115

116116
func s1(l *lexer) (stateFn, error) {
117-
return l.handleType(func(key string) stateFn {
118-
if key == "v=" {
117+
return l.handleType(func(key byte) stateFn {
118+
if key == 'v' {
119119
return unmarshalProtocolVersion
120120
}
121121
return nil
122122
})
123123
}
124124

125125
func s2(l *lexer) (stateFn, error) {
126-
return l.handleType(func(key string) stateFn {
127-
if key == "o=" {
126+
return l.handleType(func(key byte) stateFn {
127+
if key == 'o' {
128128
return unmarshalOrigin
129129
}
130130
return nil
131131
})
132132
}
133133

134134
func s3(l *lexer) (stateFn, error) {
135-
return l.handleType(func(key string) stateFn {
136-
if key == "s=" {
135+
return l.handleType(func(key byte) stateFn {
136+
if key == 's' {
137137
return unmarshalSessionName
138138
}
139139
return nil
140140
})
141141
}
142142

143143
func s4(l *lexer) (stateFn, error) {
144-
return l.handleType(func(key string) stateFn {
144+
return l.handleType(func(key byte) stateFn {
145145
switch key {
146-
case "i=":
146+
case 'i':
147147
return unmarshalSessionInformation
148-
case "u=":
148+
case 'u':
149149
return unmarshalURI
150-
case "e=":
150+
case 'e':
151151
return unmarshalEmail
152-
case "p=":
152+
case 'p':
153153
return unmarshalPhone
154-
case "c=":
154+
case 'c':
155155
return unmarshalSessionConnectionInformation
156-
case "b=":
156+
case 'b':
157157
return unmarshalSessionBandwidth
158-
case "t=":
158+
case 't':
159159
return unmarshalTiming
160160
}
161161
return nil
162162
})
163163
}
164164

165165
func s5(l *lexer) (stateFn, error) {
166-
return l.handleType(func(key string) stateFn {
166+
return l.handleType(func(key byte) stateFn {
167167
switch key {
168-
case "b=":
168+
case 'b':
169169
return unmarshalSessionBandwidth
170-
case "t=":
170+
case 't':
171171
return unmarshalTiming
172172
}
173173
return nil
174174
})
175175
}
176176

177177
func s6(l *lexer) (stateFn, error) {
178-
return l.handleType(func(key string) stateFn {
178+
return l.handleType(func(key byte) stateFn {
179179
switch key {
180-
case "p=":
180+
case 'p':
181181
return unmarshalPhone
182-
case "c=":
182+
case 'c':
183183
return unmarshalSessionConnectionInformation
184-
case "b=":
184+
case 'b':
185185
return unmarshalSessionBandwidth
186-
case "t=":
186+
case 't':
187187
return unmarshalTiming
188188
}
189189
return nil
190190
})
191191
}
192192

193193
func s7(l *lexer) (stateFn, error) {
194-
return l.handleType(func(key string) stateFn {
194+
return l.handleType(func(key byte) stateFn {
195195
switch key {
196-
case "u=":
196+
case 'u':
197197
return unmarshalURI
198-
case "e=":
198+
case 'e':
199199
return unmarshalEmail
200-
case "p=":
200+
case 'p':
201201
return unmarshalPhone
202-
case "c=":
202+
case 'c':
203203
return unmarshalSessionConnectionInformation
204-
case "b=":
204+
case 'b':
205205
return unmarshalSessionBandwidth
206-
case "t=":
206+
case 't':
207207
return unmarshalTiming
208208
}
209209
return nil
210210
})
211211
}
212212

213213
func s8(l *lexer) (stateFn, error) {
214-
return l.handleType(func(key string) stateFn {
214+
return l.handleType(func(key byte) stateFn {
215215
switch key {
216-
case "c=":
216+
case 'c':
217217
return unmarshalSessionConnectionInformation
218-
case "b=":
218+
case 'b':
219219
return unmarshalSessionBandwidth
220-
case "t=":
220+
case 't':
221221
return unmarshalTiming
222222
}
223223
return nil
224224
})
225225
}
226226

227227
func s9(l *lexer) (stateFn, error) {
228-
return l.handleType(func(key string) stateFn {
228+
return l.handleType(func(key byte) stateFn {
229229
switch key {
230-
case "z=":
230+
case 'z':
231231
return unmarshalTimeZones
232-
case "k=":
232+
case 'k':
233233
return unmarshalSessionEncryptionKey
234-
case "a=":
234+
case 'a':
235235
return unmarshalSessionAttribute
236-
case "r=":
236+
case 'r':
237237
return unmarshalRepeatTimes
238-
case "t=":
238+
case 't':
239239
return unmarshalTiming
240-
case "m=":
240+
case 'm':
241241
return unmarshalMediaDescription
242242
}
243243
return nil
244244
})
245245
}
246246

247247
func s10(l *lexer) (stateFn, error) {
248-
return l.handleType(func(key string) stateFn {
248+
return l.handleType(func(key byte) stateFn {
249249
switch key {
250-
case "e=":
250+
case 'e':
251251
return unmarshalEmail
252-
case "p=":
252+
case 'p':
253253
return unmarshalPhone
254-
case "c=":
254+
case 'c':
255255
return unmarshalSessionConnectionInformation
256-
case "b=":
256+
case 'b':
257257
return unmarshalSessionBandwidth
258-
case "t=":
258+
case 't':
259259
return unmarshalTiming
260260
}
261261
return nil
262262
})
263263
}
264264

265265
func s11(l *lexer) (stateFn, error) {
266-
return l.handleType(func(key string) stateFn {
266+
return l.handleType(func(key byte) stateFn {
267267
switch key {
268-
case "a=":
268+
case 'a':
269269
return unmarshalSessionAttribute
270-
case "m=":
270+
case 'm':
271271
return unmarshalMediaDescription
272272
}
273273
return nil
274274
})
275275
}
276276

277277
func s12(l *lexer) (stateFn, error) {
278-
return l.handleType(func(key string) stateFn {
278+
return l.handleType(func(key byte) stateFn {
279279
switch key {
280-
case "a=":
280+
case 'a':
281281
return unmarshalMediaAttribute
282-
case "k=":
282+
case 'k':
283283
return unmarshalMediaEncryptionKey
284-
case "b=":
284+
case 'b':
285285
return unmarshalMediaBandwidth
286-
case "c=":
286+
case 'c':
287287
return unmarshalMediaConnectionInformation
288-
case "i=":
288+
case 'i':
289289
return unmarshalMediaTitle
290-
case "m=":
290+
case 'm':
291291
return unmarshalMediaDescription
292292
}
293293
return nil
294294
})
295295
}
296296

297297
func s13(l *lexer) (stateFn, error) {
298-
return l.handleType(func(key string) stateFn {
298+
return l.handleType(func(key byte) stateFn {
299299
switch key {
300-
case "a=":
300+
case 'a':
301301
return unmarshalSessionAttribute
302-
case "k=":
302+
case 'k':
303303
return unmarshalSessionEncryptionKey
304-
case "m=":
304+
case 'm':
305305
return unmarshalMediaDescription
306306
}
307307
return nil
308308
})
309309
}
310310

311311
func s14(l *lexer) (stateFn, error) {
312-
return l.handleType(func(key string) stateFn {
312+
return l.handleType(func(key byte) stateFn {
313313
switch key {
314-
case "a=":
314+
case 'a':
315315
return unmarshalMediaAttribute
316-
case "k=":
316+
case 'k':
317317
// Non-spec ordering
318318
return unmarshalMediaEncryptionKey
319-
case "b=":
319+
case 'b':
320320
// Non-spec ordering
321321
return unmarshalMediaBandwidth
322-
case "c=":
322+
case 'c':
323323
// Non-spec ordering
324324
return unmarshalMediaConnectionInformation
325-
case "i=":
325+
case 'i':
326326
// Non-spec ordering
327327
return unmarshalMediaTitle
328-
case "m=":
328+
case 'm':
329329
return unmarshalMediaDescription
330330
}
331331
return nil
332332
})
333333
}
334334

335335
func s15(l *lexer) (stateFn, error) {
336-
return l.handleType(func(key string) stateFn {
336+
return l.handleType(func(key byte) stateFn {
337337
switch key {
338-
case "a=":
338+
case 'a':
339339
return unmarshalMediaAttribute
340-
case "k=":
340+
case 'k':
341341
return unmarshalMediaEncryptionKey
342-
case "b=":
342+
case 'b':
343343
return unmarshalMediaBandwidth
344-
case "c=":
344+
case 'c':
345345
return unmarshalMediaConnectionInformation
346-
case "i=":
346+
case 'i':
347347
// Non-spec ordering
348348
return unmarshalMediaTitle
349-
case "m=":
349+
case 'm':
350350
return unmarshalMediaDescription
351351
}
352352
return nil
353353
})
354354
}
355355

356356
func s16(l *lexer) (stateFn, error) {
357-
return l.handleType(func(key string) stateFn {
357+
return l.handleType(func(key byte) stateFn {
358358
switch key {
359-
case "a=":
359+
case 'a':
360360
return unmarshalMediaAttribute
361-
case "k=":
361+
case 'k':
362362
return unmarshalMediaEncryptionKey
363-
case "c=":
363+
case 'c':
364364
return unmarshalMediaConnectionInformation
365-
case "b=":
365+
case 'b':
366366
return unmarshalMediaBandwidth
367-
case "i=":
367+
case 'i':
368368
// Non-spec ordering
369369
return unmarshalMediaTitle
370-
case "m=":
370+
case 'm':
371371
return unmarshalMediaDescription
372372
}
373373
return nil

Diff for: ‎util.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -315,11 +315,11 @@ type lexer struct {
315315
baseLexer
316316
}
317317

318-
type keyToState func(key string) stateFn
318+
type keyToState func(key byte) stateFn
319319

320320
func (l *lexer) handleType(fn keyToState) (stateFn, error) {
321321
key, err := l.readType()
322-
if errors.Is(err, io.EOF) && key == "" {
322+
if errors.Is(err, io.EOF) && key == 0 {
323323
return nil, nil //nolint:nilnil
324324
} else if err != nil {
325325
return nil, err

0 commit comments

Comments
 (0)
Please sign in to comment.