Skip to content
This repository has been archived by the owner on May 2, 2018. It is now read-only.

Commit

Permalink
cmd/internal/obj, cmd/link: put all symbol data in one contiguous sec…
Browse files Browse the repository at this point in the history
…tion

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 <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: David Crawshaw <[email protected]>
  • Loading branch information
mwhudson committed Mar 21, 2016
1 parent 34f0c0b commit 36d5650
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 51 deletions.
27 changes: 16 additions & 11 deletions src/cmd/internal/goobj/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,16 @@ var (

// An objReader is an object file reader.
type objReader struct {
p *Package
b *bufio.Reader
f io.ReadSeeker
err error
offset int64
limit int64
tmp [256]byte
pkg string
pkgprefix string
p *Package
b *bufio.Reader
f io.ReadSeeker
err error
offset int64
dataOffset int64
limit int64
tmp [256]byte
pkg string
pkgprefix string
}

// importPathToPrefix returns the prefix that will be used in the
Expand Down Expand Up @@ -416,8 +417,8 @@ func (r *objReader) readRef() {
// readData reads a data reference from the input file.
func (r *objReader) readData() Data {
n := r.readInt()
d := Data{Offset: r.offset, Size: int64(n)}
r.skip(int64(n))
d := Data{Offset: r.dataOffset, Size: int64(n)}
r.dataOffset += int64(n)
return d
}

Expand Down Expand Up @@ -610,6 +611,10 @@ func (r *objReader) parseObject(prefix []byte) error {
r.readRef()
}

dataLength := r.readInt()
r.dataOffset = r.offset
r.skip(int64(dataLength))

// Symbols.
for {
if b := r.readByte(); b != 0xfe {
Expand Down
49 changes: 35 additions & 14 deletions src/cmd/internal/obj/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@
// - byte 1 - version number
// - sequence of strings giving dependencies (imported packages)
// - 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)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
Expand Down Expand Up @@ -96,9 +98,6 @@
//
// 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.
// - 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

Expand Down Expand Up @@ -319,15 +318,42 @@ func Writeobjfile(ctxt *Link, b *Biobuf) {
}
wrstring(b, "")

var dataLength int64
// Emit symbol references.
for _, s := range ctxt.Text {
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 {
writerefs(ctxt, b, s)
dataLength += int64(len(s.P))
}
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.
for _, s := range ctxt.Text {
writesym(ctxt, b, s)
Expand Down Expand Up @@ -480,7 +506,7 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
wrint(b, flags)
wrint(b, s.Size)
wrsym(b, s.Gotype)
wrdata(b, s.P)
wrint(b, int64(len(s.P)))

wrint(b, int64(len(s.R)))
var r *Reloc
Expand Down Expand Up @@ -521,12 +547,12 @@ func writesym(ctxt *Link, b *Biobuf, s *LSym) {
}

pc := s.Pcln
wrdata(b, pc.Pcsp.P)
wrdata(b, pc.Pcfile.P)
wrdata(b, pc.Pcline.P)
wrint(b, int64(len(pc.Pcsp.P)))
wrint(b, int64(len(pc.Pcfile.P)))
wrint(b, int64(len(pc.Pcline.P)))
wrint(b, int64(len(pc.Pcdata)))
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)))
for i := 0; i < len(pc.Funcdataoff); i++ {
Expand Down Expand Up @@ -564,11 +590,6 @@ func wrstring(b *Biobuf, s string) {
b.w.WriteString(s)
}

func wrdata(b *Biobuf, v []byte) {
wrint(b, int64(len(v)))
b.Write(v)
}

func wrsym(b *Biobuf, s *LSym) {
if s == nil {
wrint(b, 0)
Expand Down
42 changes: 16 additions & 26 deletions src/cmd/link/internal/ld/objfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ package ld
// - empty string (marks end of sequence)
// - sequence of sybol references used by the defined symbols
// - byte 0xff (marks end of sequence)
// - integer (length of following data)
// - data, the content of the defined symbols
// - sequence of defined symbols
// - byte 0xff (marks end of sequence)
// - magic footer: "\xff\xffgo13ld"
Expand Down Expand Up @@ -98,9 +100,6 @@ package ld
//
// 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.
// - 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 (
"bytes"
Expand Down Expand Up @@ -151,6 +150,10 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
readref(ctxt, f, pkg, pn)
}

dataLength := rdint64(f)
data := make([]byte, dataLength)
obj.Bread(f, data)

for {
c, err := f.Peek(1)
if err != nil {
Expand All @@ -159,7 +162,7 @@ func ldobjfile(ctxt *Link, f *obj.Biobuf, pkg string, length int64, pn string) {
if c[0] == 0xff {
break
}
readsym(ctxt, f, pkg, pn)
readsym(ctxt, f, &data, pkg, pn)
}

buf = [8]uint8{}
Expand All @@ -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 {
log.Fatalf("readsym out of sync")
}
Expand All @@ -184,7 +187,7 @@ func readsym(ctxt *Link, f *obj.Biobuf, pkg string, pn string) {
local := flags&2 != 0
size := rdint(f)
typ := rdsym(ctxt, f, pkg)
data := rddata(f)
data := rddata(f, buf)
nreloc := rdint(f)

var dup *LSym
Expand Down Expand Up @@ -283,14 +286,14 @@ overwrite:

s.Pcln = new(Pcln)
pc := s.Pcln
pc.Pcsp.P = rddata(f)
pc.Pcfile.P = rddata(f)
pc.Pcline.P = rddata(f)
pc.Pcsp.P = rddata(f, buf)
pc.Pcfile.P = rddata(f, buf)
pc.Pcline.P = rddata(f, buf)
n = rdint(f)
pc.Pcdata = make([]Pcdata, n)
pc.Npcdata = n
for i := 0; i < n; i++ {
pc.Pcdata[i].P = rddata(f)
pc.Pcdata[i].P = rddata(f, buf)
}
n = rdint(f)
pc.Funcdata = make([]*LSym, n)
Expand Down Expand Up @@ -482,23 +485,10 @@ func rdstring(f *obj.Biobuf) string {
return string(rdBuf[:n])
}

const rddataBufMax = 1 << 14

var rddataBuf = make([]byte, rddataBufMax)

func rddata(f *obj.Biobuf) []byte {
var p []byte
func rddata(f *obj.Biobuf, buf *[]byte) []byte {
n := rdint(f)
if n > rddataBufMax {
p = make([]byte, n)
} else {
if len(rddataBuf) < n {
rddataBuf = make([]byte, rddataBufMax)
}
p = rddataBuf[:n:n]
rddataBuf = rddataBuf[n:]
}
obj.Bread(f, p)
p := (*buf)[:n:n]
*buf = (*buf)[n:]
return p
}

Expand Down

0 comments on commit 36d5650

Please sign in to comment.