Skip to content

Commit 0f062c1

Browse files
committed
speed up dictionary key unmarshalling
1 parent aca28dc commit 0f062c1

File tree

3 files changed

+46
-41
lines changed

3 files changed

+46
-41
lines changed

README.md

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,29 +25,31 @@ data, err := bencode.Unmarshal(value)
2525

2626
## Performance
2727

28-
### Go 1.13.1, Debian 9.1, i7-7700
28+
### Go 1.16, Debian 9.1, i7-7700
2929

3030
### Marshal
3131

32-
| Library | Time | Bytes Allocated | Objects Allocated |
33-
| :----------------- | :--------: | :-------------: | :---------------: |
34-
| IncSW/go-bencode | 485 ns/op | 16 B/op | 2 allocs/op |
35-
| marksamman/bencode | 897 ns/op | 400 B/op | 8 allocs/op |
36-
| chihaya/bencode | 1846 ns/op | 1010 B/op | 53 allocs/op |
37-
| nabilanam/bencode | 2027 ns/op | 1216 B/op | 44 allocs/op |
38-
| jackpal/bencode-go | 4968 ns/op | 2128 B/op | 57 allocs/op |
39-
| zeebo/bencode | 5147 ns/op | 1488 B/op | 45 allocs/op |
32+
| Library | Time | Bytes Allocated | Objects Allocated |
33+
| :------------------ | :---------: | :-------------: | :---------------: |
34+
| IncSW/go-bencode | 795.9 ns/op | 176 B/op | 6 allocs/op |
35+
| marksamman/bencode | 820.3 ns/op | 384 B/op | 8 allocs/op |
36+
| cristalhq/bencode | 994.2 ns/op | 928 B/op | 4 allocs/op |
37+
| aleksatr/go-bencode | 1061 ns/op | 736 B/op | 9 allocs/op |
38+
| nabilanam/bencode | 2103 ns/op | 1192 B/op | 44 allocs/op |
39+
| jackpal/bencode-go | 4676 ns/op | 2016 B/op | 45 allocs/op |
40+
| zeebo/bencode | 4889 ns/op | 1376 B/op | 33 allocs/op |
4041

4142
### Unmarshal
4243

43-
| Library | Time | Bytes Allocated | Objects Allocated |
44-
| :----------------- | :--------: | :-------------: | :---------------: |
45-
| nabilanam/bencode | 1341 ns/op | 1264 B/op | 39 allocs/op |
46-
| IncSW/go-bencode | 1435 ns/op | 1248 B/op | 25 allocs/op |
47-
| jackpal/bencode-go | 2652 ns/op | 1712 B/op | 59 allocs/op |
48-
| marksamman/bencode | 2877 ns/op | 5920 B/op | 66 allocs/op |
49-
| chihaya/bencode | 2896 ns/op | 5904 B/op | 61 allocs/op |
50-
| zeebo/bencode | 6595 ns/op | 6576 B/op | 99 allocs/op |
44+
| Library | Time | Bytes Allocated | Objects Allocated |
45+
| :------------------ | :--------: | :-------------: | :---------------: |
46+
| IncSW/go-bencode | 1149 ns/op | 960 B/op | 18 allocs/op |
47+
| cristalhq/bencode | 1160 ns/op | 960 B/op | 18 allocs/op |
48+
| nabilanam/bencode | 1379 ns/op | 1240 B/op | 39 allocs/op |
49+
| aleksatr/go-bencode | 2270 ns/op | 1816 B/op | 51 allocs/op |
50+
| jackpal/bencode-go | 2577 ns/op | 1688 B/op | 59 allocs/op |
51+
| marksamman/bencode | 2725 ns/op | 5768 B/op | 54 allocs/op |
52+
| zeebo/bencode | 5988 ns/op | 6392 B/op | 92 allocs/op |
5153

5254
## License
5355

unmarshaler.go

Lines changed: 26 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -64,38 +64,41 @@ func (u *unmarshaler) unmarshal() (interface{}, error) {
6464
u.cursor += 1
6565
return dictionary, nil
6666
}
67-
value, err := u.unmarshal()
67+
key, err := u.unmarshalString()
6868
if err != nil {
69-
return nil, err
70-
}
71-
key, ok := value.([]byte)
72-
if !ok {
7369
return nil, errors.New("bencode: non-string dictionary key")
7470
}
75-
value, err = u.unmarshal()
71+
value, err := u.unmarshal()
7672
if err != nil {
7773
return nil, err
7874
}
7975
dictionary[b2s(key)] = value
8076
}
8177

8278
default:
83-
index := bytes.IndexByte(u.data[u.cursor:], ':')
84-
if index == -1 {
85-
return nil, errors.New("bencode: invalid string field")
86-
}
87-
index += u.cursor
88-
stringLength, err := strconv.ParseInt(b2s(u.data[u.cursor:index]), 10, 64)
89-
if err != nil {
90-
return nil, err
91-
}
92-
index += 1
93-
endIndex := index + int(stringLength)
94-
if endIndex > u.length {
95-
return nil, errors.New("bencode: not a valid bencoded string")
96-
}
97-
value := u.data[index:endIndex]
98-
u.cursor = endIndex
99-
return value, nil
79+
return u.unmarshalString()
80+
}
81+
}
82+
83+
func (u *unmarshaler) unmarshalString() ([]byte, error) {
84+
if u.data[u.cursor] < '0' || u.data[u.cursor] > '9' {
85+
return nil, errors.New("bencode: invalid string field")
86+
}
87+
index := bytes.IndexByte(u.data[u.cursor:], ':')
88+
if index == -1 {
89+
return nil, errors.New("bencode: invalid string field")
90+
}
91+
index += u.cursor
92+
stringLength, err := strconv.ParseInt(b2s(u.data[u.cursor:index]), 10, 64)
93+
if err != nil {
94+
return nil, err
95+
}
96+
index += 1
97+
endIndex := index + int(stringLength)
98+
if endIndex > u.length {
99+
return nil, errors.New("bencode: not a valid bencoded string")
100100
}
101+
value := u.data[index:endIndex]
102+
u.cursor = endIndex
103+
return value, nil
101104
}

unmarshaler_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
var (
10-
unmarshalTestData = []byte("d4:infod6:lengthi170917888e12:piece lengthi262144e4:name30:debian-8.8.0-arm64-netinst.isoe8:announce38:udp://tracker.publicbt.com:80/announce13:announce-listll38:udp://tracker.publicbt.com:80/announceel44:udp://tracker.openbittorrent.com:80/announceee7:comment33:Debian CD from cdimage.debian.orge")
10+
unmarshalTestData = []byte("d8:announce38:udp://tracker.publicbt.com:80/announce13:announce-listll38:udp://tracker.publicbt.com:80/announceel44:udp://tracker.openbittorrent.com:80/announceee7:comment33:Debian CD from cdimage.debian.org4:infod6:lengthi170917888e4:name30:debian-8.8.0-arm64-netinst.iso12:piece lengthi262144eee")
1111
unmarshalWrongTestData = []byte("d4:infod6:lengthi170917888e12:piece lengthi262144e4:name30:debian-8.8.0-arm64-netinst.isoe8:announce38:udp://tracker.publicbt.com:80/announce13:announce-listll38:udp://tracker.publicbt.com:80/announceel44:udp://tracker.openbittorrent.com:80/announceee7:comment35:Debian CD from cdimage.debian.orge")
1212
)
1313

0 commit comments

Comments
 (0)