mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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>
This commit is contained in:
parent
9d669ed47a
commit
e3cb381704
2 changed files with 15 additions and 17 deletions
|
|
@ -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)
|
err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path)
|
||||||
|
|
||||||
case "$$B\n":
|
case "$$B\n":
|
||||||
var data []byte
|
var exportFormat byte
|
||||||
data, err = io.ReadAll(buf)
|
exportFormat, err = buf.ReadByte()
|
||||||
if err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// The indexed export format starts with an 'i'; the older
|
// The indexed export format starts with an 'i'; the older
|
||||||
// binary export format starts with a 'c', 'd', or 'v'
|
// binary export format starts with a 'c', 'd', or 'v'
|
||||||
// (from "version"). Select appropriate importer.
|
// (from "version"). Select appropriate importer.
|
||||||
if len(data) > 0 && data[0] == 'i' {
|
if err == nil && exportFormat == 'i' {
|
||||||
_, pkg, err = iImportData(fset, packages, data[1:], id)
|
pkg, err = iImportData(fset, packages, buf, id)
|
||||||
} else {
|
} else {
|
||||||
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
|
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
package gcimporter
|
package gcimporter
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -20,7 +21,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type intReader struct {
|
type intReader struct {
|
||||||
*bytes.Reader
|
*bufio.Reader
|
||||||
path string
|
path string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,7 +62,7 @@ const (
|
||||||
// and returns the number of bytes consumed and a reference to the package.
|
// 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
|
// If the export data version is not recognized or the format is otherwise
|
||||||
// compromised, an error is returned.
|
// 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
|
const currentVersion = 1
|
||||||
version := int64(-1)
|
version := int64(-1)
|
||||||
defer func() {
|
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())
|
version = int64(r.uint64())
|
||||||
switch version {
|
switch version {
|
||||||
|
|
@ -86,10 +87,12 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
||||||
sLen := int64(r.uint64())
|
sLen := int64(r.uint64())
|
||||||
dLen := int64(r.uint64())
|
dLen := int64(r.uint64())
|
||||||
|
|
||||||
whence, _ := r.Seek(0, io.SeekCurrent)
|
data := make([]byte, sLen+dLen)
|
||||||
stringData := data[whence : whence+sLen]
|
if _, err := io.ReadFull(r, data); err != nil {
|
||||||
declData := data[whence+sLen : whence+sLen+dLen]
|
errorf("cannot read %d bytes of stringData and declData: %s", len(data), err)
|
||||||
r.Seek(sLen+dLen, io.SeekCurrent)
|
}
|
||||||
|
stringData := data[:sLen]
|
||||||
|
declData := data[sLen:]
|
||||||
|
|
||||||
p := iimporter{
|
p := iimporter{
|
||||||
ipath: path,
|
ipath: path,
|
||||||
|
|
@ -165,9 +168,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
||||||
|
|
||||||
// package was imported completely and without errors
|
// package was imported completely and without errors
|
||||||
localpkg.MarkComplete()
|
localpkg.MarkComplete()
|
||||||
|
return localpkg, nil
|
||||||
consumed, _ := r.Seek(0, io.SeekCurrent)
|
|
||||||
return int(consumed), localpkg, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type iimporter struct {
|
type iimporter struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue