aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Zagursky <gvozdoder@gmail.com>2021-06-04 12:25:51 +0300
committerMatthew Dempsky <mdempsky@google.com>2021-06-05 09:28:43 +0000
commite3cb3817049ca5e9d96543500b72117f6ca659b8 (patch)
treee14e85c0f8adeed43960481d9188984ae7575a06
parent9d669ed47a502ca540c7f3329f84d89fc0c53971 (diff)
downloadgo-e3cb3817049ca5e9d96543500b72117f6ca659b8.tar.gz
go-e3cb3817049ca5e9d96543500b72117f6ca659b8.zip
go/internal/gcimporter: don't waste CPU copying bytes in `io.ReadAll`
`io.ReadAll` dynamically reallocates byte slice because it doesn't know its size in advance. We don't need to read an entire file into memory and therefore may use `bufio.Reader` to read its contents. Fixes #46564 Change-Id: Id504b1512662b6dea4775d523455896fa4162ab3 Reviewed-on: https://go-review.googlesource.com/c/go/+/325429 Reviewed-by: Dominik Honnef <dominik@honnef.co> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Trust: Matthew Dempsky <mdempsky@google.com> Trust: Dominik Honnef <dominik@honnef.co> Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Go Bot <gobot@golang.org>
-rw-r--r--src/go/internal/gcimporter/gcimporter.go11
-rw-r--r--src/go/internal/gcimporter/iimport.go21
2 files changed, 15 insertions, 17 deletions
diff --git a/src/go/internal/gcimporter/gcimporter.go b/src/go/internal/gcimporter/gcimporter.go
index b74daca246..73cf6334fd 100644
--- a/src/go/internal/gcimporter/gcimporter.go
+++ b/src/go/internal/gcimporter/gcimporter.go
@@ -145,17 +145,14 @@ func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDi
err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path)
case "$$B\n":
- var data []byte
- data, err = io.ReadAll(buf)
- if err != nil {
- break
- }
+ var exportFormat byte
+ exportFormat, err = buf.ReadByte()
// The indexed export format starts with an 'i'; the older
// binary export format starts with a 'c', 'd', or 'v'
// (from "version"). Select appropriate importer.
- if len(data) > 0 && data[0] == 'i' {
- _, pkg, err = iImportData(fset, packages, data[1:], id)
+ if err == nil && exportFormat == 'i' {
+ pkg, err = iImportData(fset, packages, buf, id)
} else {
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
}
diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go
index a3184e7641..76d47d08f1 100644
--- a/src/go/internal/gcimporter/iimport.go
+++ b/src/go/internal/gcimporter/iimport.go
@@ -8,6 +8,7 @@
package gcimporter
import (
+ "bufio"
"bytes"
"encoding/binary"
"fmt"
@@ -20,7 +21,7 @@ import (
)
type intReader struct {
- *bytes.Reader
+ *bufio.Reader
path string
}
@@ -61,7 +62,7 @@ const (
// and returns the number of bytes consumed and a reference to the package.
// If the export data version is not recognized or the format is otherwise
// compromised, an error is returned.
-func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
+func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) {
const currentVersion = 1
version := int64(-1)
defer func() {
@@ -74,7 +75,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
}
}()
- r := &intReader{bytes.NewReader(data), path}
+ r := &intReader{dataReader, path}
version = int64(r.uint64())
switch version {
@@ -86,10 +87,12 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
sLen := int64(r.uint64())
dLen := int64(r.uint64())
- whence, _ := r.Seek(0, io.SeekCurrent)
- stringData := data[whence : whence+sLen]
- declData := data[whence+sLen : whence+sLen+dLen]
- r.Seek(sLen+dLen, io.SeekCurrent)
+ data := make([]byte, sLen+dLen)
+ if _, err := io.ReadFull(r, data); err != nil {
+ errorf("cannot read %d bytes of stringData and declData: %s", len(data), err)
+ }
+ stringData := data[:sLen]
+ declData := data[sLen:]
p := iimporter{
ipath: path,
@@ -165,9 +168,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
// package was imported completely and without errors
localpkg.MarkComplete()
-
- consumed, _ := r.Seek(0, io.SeekCurrent)
- return int(consumed), localpkg, nil
+ return localpkg, nil
}
type iimporter struct {