1
0
mirror of https://github.com/golang/go synced 2024-11-11 23:40:22 -07:00

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: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
Shahar Kohanim 2016-03-09 16:23:25 +02:00 committed by David Crawshaw
parent 7177cb9fa4
commit 90a59d448e
2 changed files with 65 additions and 30 deletions

View File

@ -37,6 +37,7 @@ import (
"fmt"
"log"
"os"
"sort"
"strconv"
"strings"
)
@ -216,24 +217,6 @@ func addaddrplus4(ctxt *Link, s *LSym, t *LSym, add int64) int64 {
* sort of LSym* structures.
* 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 {
return &s.Next
@ -1127,6 +1110,36 @@ func (p *GCProg) AddSym(s *LSym) {
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) {
datsize := *datsizep
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) {
*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() {
if Debug['v'] != 0 {
fmt.Fprintf(&Bso, "%5.2f dodata\n", obj.Cputime())
@ -1231,7 +1277,7 @@ func dodata() {
}
datap = listsort(datap, datcmp, listnextp)
datap = dataSort(datap)
if Iself {
// Make .rela and .rela.plt contiguous, the ELF ABI requires this

View File

@ -67,17 +67,6 @@ func tokenize(s string) []string {
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()
func AtExit(f func()) {