Skip to content

Commit 97243b3

Browse files
committed
Improve UTF16 decoding performance
1 parent b17831c commit 97243b3

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

nettrace/parser.go

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ func (p *Parser) Err() error {
1919
return nil
2020
}
2121

22+
func (p *Parser) Skip(n int) {
23+
if n > 0 {
24+
p.Next(n)
25+
}
26+
}
27+
2228
func (p *Parser) Read(v interface{}) {
2329
if err := binary.Read(p.Buffer, binary.LittleEndian, v); err != nil {
2430
p.errs = append(p.errs, err)
@@ -33,18 +39,34 @@ func (p *Parser) Uvarint() uint64 {
3339
return n
3440
}
3541

42+
// UTF16NTS returns UTF8 string read from 2-bytes UTF16 null terminated string.
43+
// Bytes are speculatively interpreted as 2-byte ASCII chars, and decoding
44+
// takes place only if a code unit is not representable in ASCII.
3645
func (p *Parser) UTF16NTS() string {
37-
s := make([]uint16, 0, 256)
38-
var c uint16
39-
for {
40-
if p.errs != nil {
41-
return ""
46+
b := p.Bytes()
47+
s := make([]byte, 0, 64) // The capacity has been chosen empirically.
48+
for i := 0; i < len(b)-1; i += 2 {
49+
if b[i] == 0x0 {
50+
p.Skip(i + 2)
51+
break
4252
}
43-
p.Read(&c)
44-
if c == 0x0 {
53+
if b[i+1] != 0x0 {
54+
return p.decodeUTF16NTS()
55+
}
56+
s = append(s, b[i])
57+
}
58+
return string(s)
59+
}
60+
61+
func (p *Parser) decodeUTF16NTS() string {
62+
b := p.Bytes()
63+
s := make([]uint16, 0, 64)
64+
for i := 0; i < len(b)-1; i += 2 {
65+
if b[i] == 0x0 {
66+
p.Skip(i + 2)
4567
break
4668
}
47-
s = append(s, c)
69+
s = append(s, binary.LittleEndian.Uint16(b[i:(i+2)]))
4870
}
4971
return string(utf16.Decode(s))
5072
}

0 commit comments

Comments
 (0)