]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/obj, cmd/link: put all symbol data in one contiguous section
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Sun, 20 Mar 2016 21:55:20 +0000 (10:55 +1300)
committerMichael Hudson-Doyle <michael.hudson@canonical.com>
Mon, 21 Mar 2016 01:36:00 +0000 (01:36 +0000)
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: David Crawshaw <crawshaw@golang.org>
src/cmd/internal/goobj/read.go
src/cmd/internal/obj/objfile.go
src/cmd/link/internal/ld/objfile.go

index a693725e9a53dee1555b5b4a4ec6584a6506d581..6a906a46276642af78d1b3001b02725e138f5543 100644 (file)
@@ -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
@@ -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
 }
 
@@ -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 {
index 43b4be1b9f7287e00b8f8f049d0bc77e230c83d6..42ae86d62d8a8042ee84c631a8239beebc7e84f4 100644 (file)
 //     - 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"
@@ -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
 
@@ -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)
@@ -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
@@ -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++ {
@@ -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)
index b842fe15d0ced2ae296d0ed042e4c2ba226dc101..130347e7fd2869b7e54b2532358ac24f74f4b1d7 100644 (file)
@@ -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"
@@ -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"
@@ -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 {
@@ -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{}
@@ -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")
        }
@@ -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
@@ -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)
@@ -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
 }