Commit 36d5650a authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle

cmd/internal/obj, cmd/link: put all symbol data in one contiguous section

Another object file change, gives a reasonable improvement:

name       old s/op   new s/op   delta
LinkCmdGo  0.46 ± 3%  0.44 ± 9%  -3.34%  (p=0.000 n=98+82)
LinkJuju   4.09 ± 4%  3.92 ± 5%  -4.30%  (p=0.000 n=98+99)

I guess the data section could be mmap-ed instead of read, I haven't tried
that.

Change-Id: I959eee470a05526ab1579e3f5d3ede41c16c954f
Reviewed-on: https://go-review.googlesource.com/20928
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 34f0c0b3
...@@ -236,15 +236,16 @@ var ( ...@@ -236,15 +236,16 @@ var (
// An objReader is an object file reader. // An objReader is an object file reader.
type objReader struct { type objReader struct {
p *Package p *Package
b *bufio.Reader b *bufio.Reader
f io.ReadSeeker f io.ReadSeeker
err error err error
offset int64 offset int64
limit int64 dataOffset int64
tmp [256]byte limit int64
pkg string tmp [256]byte
pkgprefix string pkg string
pkgprefix string
} }
// importPathToPrefix returns the prefix that will be used in the // importPathToPrefix returns the prefix that will be used in the
...@@ -416,8 +417,8 @@ func (r *objReader) readRef() { ...@@ -416,8 +417,8 @@ func (r *objReader) readRef() {
// readData reads a data reference from the input file. // readData reads a data reference from the input file.
func (r *objReader) readData() Data { func (r *objReader) readData() Data {
n := r.readInt() n := r.readInt()
d := Data{Offset: r.offset, Size: int64(n)} d := Data{Offset: r.dataOffset, Size: int64(n)}
r.skip(int64(n)) r.dataOffset += int64(n)
return d return d
} }
...@@ -610,6 +611,10 @@ func (r *objReader) parseObject(prefix []byte) error { ...@@ -610,6 +611,10 @@ func (r *objReader) parseObject(prefix []byte) error {
r.readRef() r.readRef()
} }
dataLength := r.readInt()
r.dataOffset = r.offset
r.skip(int64(dataLength))
// Symbols. // Symbols.
for { for {
if b := r.readByte(); b != 0xfe { if b := r.readByte(); b != 0xfe {
......
...@@ -19,8 +19,10 @@ ...@@ -19,8 +19,10 @@
// - byte 1 - version number // - byte 1 - version number
// - sequence of strings giving dependencies (imported packages) // - sequence of strings giving dependencies (imported packages)
// - empty string (marks end of sequence) // - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols // - sequence of symbol references used by the defined symbols
// - byte 0xff (marks end of sequence) // - byte 0xff (marks end of sequence)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols // - sequence of defined symbols
// - byte 0xff (marks end of sequence) // - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld" // - magic footer: "\xff\xffgo13ld"
...@@ -96,9 +98,6 @@ ...@@ -96,9 +98,6 @@
// //
// TODO(rsc): The file format is good for a first pass but needs work. // TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings. // - There are SymID in the object file that should really just be strings.
// - The actual symbol memory images are interlaced with the symbol
// metadata. They should be separated, to reduce the I/O required to
// load just the metadata.
package obj package obj
...@@ -319,15 +318,42 @@ func Writeobjfile(ctxt *Link, b *Biobuf) { ...@@ -319,15 +318,42 @@ func Writeobjfile(ctxt *Link, b *Biobuf) {
} }
wrstring(b, "") wrstring(b, "")
var dataLength int64
// Emit symbol references. // Emit symbol references.
for _, s := range ctxt.Text { for _, s := range ctxt.Text {
writerefs(ctxt, b, s) writerefs(ctxt, b, s)
dataLength += int64(len(s.P))
pc := s.Pcln
dataLength += int64(len(pc.Pcsp.P))
dataLength += int64(len(pc.Pcfile.P))
dataLength += int64(len(pc.Pcline.P))
for i := 0; i < len(pc.Pcdata); i++ {
dataLength += int64(len(pc.Pcdata[i].P))
}
} }
for _, s := range ctxt.Data { for _, s := range ctxt.Data {
writerefs(ctxt, b, s) writerefs(ctxt, b, s)
dataLength += int64(len(s.P))
} }
Bputc(b, 0xff) Bputc(b, 0xff)
// Write data block
wrint(b, dataLength)
for _, s := range ctxt.Text {
b.w.Write(s.P)
pc := s.Pcln
b.w.Write(pc.Pcsp.P)
b.w.Write(pc.Pcfile.P)
b.w.Write(pc.Pcline.P)
for i := 0; i < len(pc.Pcdata); i++ {
b.w.Write(pc.Pcdata[i].P)
}
}
for _, s := range ctxt.Data {
b.w.Write(s.P)
}
// Emit symbols. // Emit symbols.
for _, s := range ctxt.Text { for _, s := range ctxt.Text {
writesym(ctxt, b, s) writesym(ctxt, b, s)
...@@ -480,7 +506,7 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) { ...@@ -480,7 +506,7 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
wrint(b, flags) wrint(b, flags)
wrint(b, s.Size) wrint(b, s.Size)
wrsym(b, s.Gotype) wrsym(b, s.Gotype)
wrdata(b, s.P) wrint(b, int64(len(s.P)))
wrint(b, int64(len(s.R))) wrint(b, int64(len(s.R)))
var r *Reloc var r *Reloc
...@@ -521,12 +547,12 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) { ...@@ -521,12 +547,12 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
} }
pc := s.Pcln pc := s.Pcln
wrdata(b, pc.Pcsp.P) wrint(b, int64(len(pc.Pcsp.P)))
wrdata(b, pc.Pcfile.P) wrint(b, int64(len(pc.Pcfile.P)))
wrdata(b, pc.Pcline.P) wrint(b, int64(len(pc.Pcline.P)))
wrint(b, int64(len(pc.Pcdata))) wrint(b, int64(len(pc.Pcdata)))
for i := 0; i < len(pc.Pcdata); i++ { for i := 0; i < len(pc.Pcdata); i++ {
wrdata(b, pc.Pcdata[i].P) wrint(b, int64(len(pc.Pcdata[i].P)))
} }
wrint(b, int64(len(pc.Funcdataoff))) wrint(b, int64(len(pc.Funcdataoff)))
for i := 0; i < len(pc.Funcdataoff); i++ { for i := 0; i < len(pc.Funcdataoff); i++ {
...@@ -564,11 +590,6 @@ func wrstring(b *Biobuf, s string) { ...@@ -564,11 +590,6 @@ func wrstring(b *Biobuf, s string) {
b.w.WriteString(s) b.w.WriteString(s)
} }
func wrdata(b *Biobuf, v []byte) {
wrint(b, int64(len(v)))
b.Write(v)
}
func wrsym(b *Biobuf, s *LSym) { func wrsym(b *Biobuf, s *LSym) {
if s == nil { if s == nil {
wrint(b, 0) wrint(b, 0)
......
...@@ -23,6 +23,8 @@ package ld ...@@ -23,6 +23,8 @@ package ld
// - empty string (marks end of sequence) // - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols // - sequence of sybol references used by the defined symbols
// - byte 0xff (marks end of sequence) // - byte 0xff (marks end of sequence)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols // - sequence of defined symbols
// - byte 0xff (marks end of sequence) // - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld" // - magic footer: "\xff\xffgo13ld"
...@@ -98,9 +100,6 @@ package ld ...@@ -98,9 +100,6 @@ package ld
// //
// TODO(rsc): The file format is good for a first pass but needs work. // TODO(rsc): The file format is good for a first pass but needs work.
// - There are SymID in the object file that should really just be strings. // - There are SymID in the object file that should really just be strings.
// - The actual symbol memory images are interlaced with the symbol
// metadata. They should be separated, to reduce the I/O required to
// load just the metadata.
import ( import (
"bytes" "bytes"
...@@ -151,6 +150,10 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -151,6 +150,10 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
readref(ctxt, f, pkg, pn) readref(ctxt, f, pkg, pn)
} }
dataLength := rdint64(f)
data := make([]byte, dataLength)
obj.Bread(f, data)
for { for {
c, err := f.Peek(1) c, err := f.Peek(1)
if err != nil { if err != nil {
...@@ -159,7 +162,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -159,7 +162,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
if c[0] == 0xff { if c[0] == 0xff {
break break
} }
readsym(ctxt, f, pkg, pn) readsym(ctxt, f, &data, pkg, pn)
} }
buf = [8]uint8{} buf = [8]uint8{}
...@@ -173,7 +176,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) { ...@@ -173,7 +176,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
} }
} }
func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) { func readsym(ctxt *Link, f *obj.Biobuf, buf *[]byte, pkg string, pn string) {
if obj.Bgetc(f) != 0xfe { if obj.Bgetc(f) != 0xfe {
log.Fatalf("readsym out of sync") log.Fatalf("readsym out of sync")
} }
...@@ -184,7 +187,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) { ...@@ -184,7 +187,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
local := flags&2 != 0 local := flags&2 != 0
size := rdint(f) size := rdint(f)
typ := rdsym(ctxt, f, pkg) typ := rdsym(ctxt, f, pkg)
data := rddata(f) data := rddata(f, buf)
nreloc := rdint(f) nreloc := rdint(f)
var dup *LSym var dup *LSym
...@@ -283,14 +286,14 @@ overwrite: ...@@ -283,14 +286,14 @@ overwrite:
s.Pcln = new(Pcln) s.Pcln = new(Pcln)
pc := s.Pcln pc := s.Pcln
pc.Pcsp.P = rddata(f) pc.Pcsp.P = rddata(f, buf)
pc.Pcfile.P = rddata(f) pc.Pcfile.P = rddata(f, buf)
pc.Pcline.P = rddata(f) pc.Pcline.P = rddata(f, buf)
n = rdint(f) n = rdint(f)
pc.Pcdata = make([]Pcdata, n) pc.Pcdata = make([]Pcdata, n)
pc.Npcdata = n pc.Npcdata = n
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
pc.Pcdata[i].P = rddata(f) pc.Pcdata[i].P = rddata(f, buf)
} }
n = rdint(f) n = rdint(f)
pc.Funcdata = make([]*LSym, n) pc.Funcdata = make([]*LSym, n)
...@@ -482,23 +485,10 @@ func rdstring(f *obj.Biobuf) string { ...@@ -482,23 +485,10 @@ func rdstring(f *obj.Biobuf) string {
return string(rdBuf[:n]) return string(rdBuf[:n])
} }
const rddataBufMax = 1 << 14 func rddata(f *obj.Biobuf, buf *[]byte) []byte {
var rddataBuf = make([]byte, rddataBufMax)
func rddata(f *obj.Biobuf) []byte {
var p []byte
n := rdint(f) n := rdint(f)
if n > rddataBufMax { p := (*buf)[:n:n]
p = make([]byte, n) *buf = (*buf)[n:]
} else {
if len(rddataBuf) < n {
rddataBuf = make([]byte, rddataBufMax)
}
p = rddataBuf[:n:n]
rddataBuf = rddataBuf[n:]
}
obj.Bread(f, p)
return p return p
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment