Commit 90a59d44 authored by Shahar Kohanim's avatar Shahar Kohanim Committed by David Crawshaw

cmd/link: use stdlib sort in dodata

Speeds up linking cmd/go by 1.7%

name       old s/op   new s/op   delta
LinkCmdGo  0.58 ± 4%  0.57 ± 5%  -1.74%  (p=0.000 n=96+97)

Change-Id: I7844cf4e2eeac260318de2b6ddf52ce07a6e00f5
Reviewed-on: https://go-review.googlesource.com/20915
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Crawshaw <crawshaw@golang.org>
parent 7177cb9f
...@@ -37,6 +37,7 @@ import ( ...@@ -37,6 +37,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"sort"
"strconv" "strconv"
"strings" "strings"
) )
...@@ -216,24 +217,6 @@ func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 { ...@@ -216,24 +217,6 @@ func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
* sort of LSym* structures. * sort of LSym* structures.
* Used for the data block. * Used for the data block.
*/ */
func datcmp(s1 *LSym, s2 *LSym) int {
if s1.Type != s2.Type {
return int(s1.Type) - int(s2.Type)
}
// For ppc64, we want to interleave the .got and .toc sections
// from input files. Both are type SELFGOT, so in that case
// fall through to the name comparison (conveniently, .got
// sorts before .toc).
if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
if s1.Size < s2.Size {
return -1
}
return +1
}
return stringsCompare(s1.Name, s2.Name)
}
func listnextp(s *LSym) **LSym { func listnextp(s *LSym) **LSym {
return &s.Next return &s.Next
...@@ -1127,6 +1110,36 @@ func (p *GCProg) AddSym(s *LSym) { ...@@ -1127,6 +1110,36 @@ func (p *GCProg) AddSym(s *LSym) {
p.w.Append(prog[4:], nptr) p.w.Append(prog[4:], nptr)
} }
type dataSortKey struct {
// keep sort keys inline to improve cache behaviour while sorting
Type int16
Size int64
Name string
Lsym *LSym
}
type dataSlice []dataSortKey
func (d dataSlice) Len() int { return len(d) }
func (d dataSlice) Swap(i, j int) { d[i], d[j] = d[j], d[i] }
func (d dataSlice) Less(i, j int) bool {
s1, s2 := &d[i], &d[j]
if s1.Type != s2.Type {
return s1.Type < s2.Type
}
// For ppc64, we want to interleave the .got and .toc sections
// from input files. Both are type SELFGOT, so in that case
// fall through to the name comparison (conveniently, .got
// sorts before .toc).
if s1.Type != obj.SELFGOT && s1.Size != s2.Size {
return s1.Size < s2.Size
}
return s1.Name < s2.Name
}
func growdatsize(datsizep *int64, s *LSym) { func growdatsize(datsizep *int64, s *LSym) {
datsize := *datsizep datsize := *datsizep
const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31) const cutoff int64 = 2e9 // 2 GB (or so; looks better in errors than 2^31)
...@@ -1141,6 +1154,39 @@ func growdatsize(datsizep *int64, s *LSym) { ...@@ -1141,6 +1154,39 @@ func growdatsize(datsizep *int64, s *LSym) {
*datsizep = datsize + s.Size *datsizep = datsize + s.Size
} }
func list2Slice(head *LSym) dataSlice {
n := 0
for s := datap; s != nil; s = s.Next {
n++
}
slice := make(dataSlice, n)
i := 0
for s := datap; s != nil; s = s.Next {
k := &slice[i]
k.Type = s.Type
k.Size = s.Size
k.Name = s.Name
k.Lsym = s
i++
}
return slice
}
func slice2List(d dataSlice) *LSym {
for i := 0; i < len(d)-1; i++ {
d[i].Lsym.Next = d[i+1].Lsym
}
d[len(d)-1].Lsym.Next = nil
return d[0].Lsym
}
func dataSort(head *LSym) *LSym {
d := list2Slice(head)
sort.Sort(d)
return slice2List(d)
}
func dodata() { func dodata() {
if Debug['v'] != 0 { if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime()) fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
...@@ -1231,7 +1277,7 @@ func dodata() { ...@@ -1231,7 +1277,7 @@ func dodata() {
} }
datap = listsort(datap, datcmp, listnextp) datap = dataSort(datap)
if Iself { if Iself {
// Make .rela and .rela.plt contiguous, the ELF ABI requires this // Make .rela and .rela.plt contiguous, the ELF ABI requires this
......
...@@ -67,17 +67,6 @@ func tokenize(s string) []string { ...@@ -67,17 +67,6 @@ func tokenize(s string) []string {
return f return f
} }
// strings.Compare, introduced in Go 1.5.
func stringsCompare(a, b string) int {
if a == b {
return 0
}
if a < b {
return -1
}
return +1
}
var atExitFuncs []func() var atExitFuncs []func()
func AtExit(f func()) { func AtExit(f func()) {
......
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