summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2009-12-01 21:44:24 -0800
committerRob Pike <r@golang.org>2009-12-01 21:44:24 -0800
commitfe281ceb3e84bf3f8fee62b41ae2f177650ae00d (patch)
treeaeb74068d7c0ea3f3bc000f93e8e0e1c5d8a28dd
parentc0aa4181512776f35d60f61a7c64e6a37364332d (diff)
downloadgolang-fe281ceb3e84bf3f8fee62b41ae2f177650ae00d.tar.gz
make io.ReadFile use Stat.Size as a hint for preallocation
R=rsc CC=golang-dev http://codereview.appspot.com/163069
-rw-r--r--src/pkg/io/utils.go18
1 files changed, 17 insertions, 1 deletions
diff --git a/src/pkg/io/utils.go b/src/pkg/io/utils.go
index ccd611571..0e0b84ae4 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.