Skip to content

Commit a878d3d

Browse files
mateusz834gopherbot
authored andcommitted
encoding/hex: don't overallocate memory in DecodeString
Now as []byte(string) doesn't always cause heap allocation (CL 520599, #2205) we can make DecodeString simpler and more performant, by not allocating x2 the required memory. goos: linux goarch: amd64 pkg: encoding/hex cpu: AMD Ryzen 5 4600G with Radeon Graphics │ beforehex │ afterhex │ │ sec/op │ sec/op vs base │ DecodeString/256-12 197.9n ± 1% 172.2n ± 1% -13.01% (p=0.000 n=10) DecodeString/1024-12 684.9n ± 1% 598.5n ± 1% -12.61% (p=0.000 n=10) DecodeString/4096-12 2.764µ ± 0% 2.343µ ± 1% -15.23% (p=0.000 n=10) DecodeString/16384-12 10.774µ ± 1% 9.348µ ± 1% -13.23% (p=0.000 n=10) geomean 1.417µ 1.226µ -13.53% │ beforehex │ afterhex │ │ B/s │ B/s vs base │ DecodeString/256-12 1.205Gi ± 1% 1.385Gi ± 1% +14.94% (p=0.000 n=10) DecodeString/1024-12 1.393Gi ± 1% 1.593Gi ± 1% +14.42% (p=0.000 n=10) DecodeString/4096-12 1.380Gi ± 0% 1.628Gi ± 1% +17.97% (p=0.000 n=10) DecodeString/16384-12 1.416Gi ± 1% 1.632Gi ± 1% +15.25% (p=0.000 n=10) geomean 1.346Gi 1.556Gi +15.64% │ beforehex │ afterhex │ │ B/op │ B/op vs base │ DecodeString/256-12 256.0 ± 0% 128.0 ± 0% -50.00% (p=0.000 n=10) DecodeString/1024-12 1024.0 ± 0% 512.0 ± 0% -50.00% (p=0.000 n=10) DecodeString/4096-12 4.000Ki ± 0% 2.000Ki ± 0% -50.00% (p=0.000 n=10) DecodeString/16384-12 16.000Ki ± 0% 8.000Ki ± 0% -50.00% (p=0.000 n=10) geomean 2.000Ki 1.000Ki -50.00% │ beforehex │ afterhex │ │ allocs/op │ allocs/op vs base │ DecodeString/256-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ DecodeString/1024-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ DecodeString/4096-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ DecodeString/16384-12 1.000 ± 0% 1.000 ± 0% ~ (p=1.000 n=10) ¹ geomean 1.000 1.000 +0.00% Change-Id: I5676e48f222d90786ea18e808cb4ecde9de82597 GitHub-Last-Rev: aeedf3f GitHub-Pull-Request: #67259 Reviewed-on: https://go-review.googlesource.com/c/go/+/584118 Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Cherry Mui <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 59493f3 commit a878d3d

File tree

2 files changed

+15
-5
lines changed

2 files changed

+15
-5
lines changed

src/encoding/hex/hex.go

+3-5
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,9 @@ func EncodeToString(src []byte) string {
136136
// If the input is malformed, DecodeString returns
137137
// the bytes decoded before the error.
138138
func DecodeString(s string) ([]byte, error) {
139-
src := []byte(s)
140-
// We can use the source slice itself as the destination
141-
// because the decode loop increments by one and then the 'seen' byte is not used anymore.
142-
n, err := Decode(src, src)
143-
return src[:n], err
139+
dst := make([]byte, DecodedLen(len(s)))
140+
n, err := Decode(dst, []byte(s))
141+
return dst[:n], err
144142
}
145143

146144
// Dump returns a string that contains a hex dump of the given data. The format

src/encoding/hex/hex_test.go

+12
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,18 @@ func BenchmarkDecode(b *testing.B) {
275275
}
276276
}
277277

278+
func BenchmarkDecodeString(b *testing.B) {
279+
for _, size := range []int{256, 1024, 4096, 16384} {
280+
src := strings.Repeat("2b744faa", size/8)
281+
b.Run(fmt.Sprintf("%v", size), func(b *testing.B) {
282+
b.SetBytes(int64(size))
283+
for i := 0; i < b.N; i++ {
284+
sink, _ = DecodeString(src)
285+
}
286+
})
287+
}
288+
}
289+
278290
func BenchmarkDump(b *testing.B) {
279291
for _, size := range []int{256, 1024, 4096, 16384} {
280292
src := bytes.Repeat([]byte{2, 3, 5, 7, 9, 11, 13, 17}, size/8)

0 commit comments

Comments
 (0)