-
Notifications
You must be signed in to change notification settings - Fork 17.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
encoding/hex: DecodeString wastes memory #29802
Comments
I’m not sure it’s worth the required code duplication to use a smaller buffer (i.e. use less memory). It might be worth setting cap==len in the returned slice ( |
What about this: func DecodeString(s string) ([]byte, error) {
dstLen := DecodedLen(len(s))
dst := make([]byte, dstLen, dstLen)
n, err := Decode(dst, []byte(s))
return dst[:n], err
} There's no code duplication here, yet the output slice is sized as expected (by me). The Go compiler should be smart enough to figure out that Users of this function who want to append later probably already use |
I use So the Go compiler is not smart enough in your option at least in go1.11.4 |
@josharian Trimming the return value using package main
import (
"fmt"
"log"
"os"
"runtime"
"runtime/debug"
)
func main() {
large := make([]byte, 0, 1<<24)
dump("001.heapdump") // 16 MB
small := large[0 : 1<<10 : 1<<10]
large = nil
dump("002.heapdump") // still 16 MB, even though large is not accessible anymore
fmt.Println(small[0:1])
small = nil
dump("003.heapdump") // 272 kB
}
func dump(filename string) {
f, err := os.Create(filename)
if err != nil {
log.Fatalln(err)
}
runtime.GC()
debug.WriteHeapDump(f.Fd())
err = f.Close()
if err != nil {
log.Fatalln(err)
}
} |
But it's not. I filed #29810 for this.
Indeed. The only value to doing so is that it helps avoid surprise of the kind expressed in this issue. @rillig also expressed concern about "leaking data", but given that the caller already had the hex input, it's not so clear to me that this is a major concern. On balance, I don't think that we should make this change.
FWIW, this kind of thing is easier to measure using benchmarks. |
A side remark: encoding/hex is close to pointless. Printf and friends do hex conversion just fine, with careful memory management. |
Yet another side remark: it would be great if standard |
Thanks. |
What version of Go are you using?
go version go1.11.4 windows/amd64
What did you do?
https://play.golang.org/p/pbZJx5AZHpJ
What did you expect to see?
The byte slice returned by
hex.DecodeString
haslen == cap
.What did you see instead?
The byte slice returned by
hex.DecodeString
is twice as large as strictly necessary.See this rillig/pkglint commit for the real-life example where I discovered this. In a commit message shortly before that, I discovered strange sequences of hex digits in the heap dump.
The text was updated successfully, but these errors were encountered: