From: Rob Pike Date: Wed, 2 Dec 2009 05:44:24 +0000 (-0800) Subject: make io.ReadFile use Stat.Size as a hint for preallocation X-Git-Tag: weekly.2009-12-07~76 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=f9810f1b12750e83d3b76f703b9956e390ee06e7;p=gostls13.git make io.ReadFile use Stat.Size as a hint for preallocation R=rsc CC=golang-dev https://golang.org/cl/163069 --- diff --git a/src/pkg/io/utils.go b/src/pkg/io/utils.go index ccd6115711..0e0b84ae49 100644 --- a/src/pkg/io/utils.go +++ b/src/pkg/io/utils.go @@ -26,7 +26,23 @@ func ReadFile(filename string) ([]byte, os.Error) { return nil, err } defer f.Close(); - return ReadAll(f); + // It's a good but not certain bet that Stat will tell us exactly how much to + // read, so let's try it but be prepared for the answer to be wrong. + dir, err := f.Stat(); + var n uint64; + if err != nil && dir.Size < 2e9 { // Don't preallocate a huge buffer, just in case. + n = dir.Size + } + if n == 0 { + n = 1024 // No idea what's right, but zero isn't. + } + // Pre-allocate the correct size of buffer, then set its size to zero. The + // Buffer will read into the allocated space cheaply. If the size was wrong, + // we'll either waste some space off the end or reallocate as needed, but + // in the overwhelmingly common case we'll get it just right. + buf := bytes.NewBuffer(make([]byte, n)[0:0]); + _, err = Copy(buf, f); + return buf.Bytes(), err; } // WriteFile writes data to a file named by filename.