mirror of
https://github.com/golang/go
synced 2024-11-17 00:14:50 -07:00
cmd/link: use slice and bitmap for some attributes
Currently, a symbol's outer symbol, the "special" attribute, and whether a symbol is a generator symbol are represented as maps, and are accessed in some loops over nearly all reachable symbols. The map lookups are a bit expensive. For outer symbol, a non-trivial portion of the symbols have outer symbol set (e.g. type symbols, which we put into container symbols like "type:*"). Using a slice to access more efficiently. For the special and generator symbol attributes, use a bitmap. There are not many symbols have those attributes, so the bitmap is quite sparse. The bitmap is not too large anyway, so use it for now. If we want to further reduce memory usage we could consider some other data structure like a Bloom filter. Linking cmd/compile in external linking mode (on macOS/amd64) Symtab 12.9ms ± 9% 6.4ms ± 5% -50.08% (p=0.000 n=19+18) Dodata 64.9ms ±12% 57.1ms ±12% -11.90% (p=0.000 n=20+20) Asmb 36.7ms ±11% 32.8ms ± 9% -10.61% (p=0.000 n=20+18) Asmb2 26.6ms ±15% 21.9ms ±12% -17.75% (p=0.000 n=20+18) There is some increase of memory usage Munmap_GC 40.9M ± 1% 43.2M ± 0% +5.54% (p=0.000 n=20+19) The next CL will bring the memory usage back. Change-Id: Ie4347eb96c51f008b9284270de37fc880bb52d2c Reviewed-on: https://go-review.googlesource.com/c/go/+/487415 Run-TryBot: Cherry Mui <cherryyz@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Austin Clements <austin@google.com>
This commit is contained in:
parent
2c70690451
commit
21c2fdd91c
@ -1080,7 +1080,8 @@ func writeBlock(ctxt *Link, out *OutBuf, ldr *loader.Loader, syms []loader.Sym,
|
|||||||
}
|
}
|
||||||
P := out.WriteSym(ldr, s)
|
P := out.WriteSym(ldr, s)
|
||||||
st.relocsym(s, P)
|
st.relocsym(s, P)
|
||||||
if f, ok := ctxt.generatorSyms[s]; ok {
|
if ldr.IsGeneratedSym(s) {
|
||||||
|
f := ctxt.generatorSyms[s]
|
||||||
f(ctxt, s)
|
f(ctxt, s)
|
||||||
}
|
}
|
||||||
addr += int64(len(P))
|
addr += int64(len(P))
|
||||||
|
@ -220,23 +220,19 @@ type Loader struct {
|
|||||||
attrLocal Bitmap // "local" symbols, indexed by global index
|
attrLocal Bitmap // "local" symbols, indexed by global index
|
||||||
attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by global idx
|
attrNotInSymbolTable Bitmap // "not in symtab" symbols, indexed by global idx
|
||||||
attrUsedInIface Bitmap // "used in interface" symbols, indexed by global idx
|
attrUsedInIface Bitmap // "used in interface" symbols, indexed by global idx
|
||||||
|
attrSpecial Bitmap // "special" frame symbols, indexed by global idx
|
||||||
attrVisibilityHidden Bitmap // hidden symbols, indexed by ext sym index
|
attrVisibilityHidden Bitmap // hidden symbols, indexed by ext sym index
|
||||||
attrDuplicateOK Bitmap // dupOK symbols, indexed by ext sym index
|
attrDuplicateOK Bitmap // dupOK symbols, indexed by ext sym index
|
||||||
attrShared Bitmap // shared symbols, indexed by ext sym index
|
attrShared Bitmap // shared symbols, indexed by ext sym index
|
||||||
attrExternal Bitmap // external symbols, indexed by ext sym index
|
attrExternal Bitmap // external symbols, indexed by ext sym index
|
||||||
|
generatedSyms Bitmap // symbols that generate their content, indexed by ext sym idx
|
||||||
|
|
||||||
attrReadOnly map[Sym]bool // readonly data for this sym
|
attrReadOnly map[Sym]bool // readonly data for this sym
|
||||||
attrSpecial map[Sym]struct{} // "special" frame symbols
|
|
||||||
attrCgoExportDynamic map[Sym]struct{} // "cgo_export_dynamic" symbols
|
attrCgoExportDynamic map[Sym]struct{} // "cgo_export_dynamic" symbols
|
||||||
attrCgoExportStatic map[Sym]struct{} // "cgo_export_static" symbols
|
attrCgoExportStatic map[Sym]struct{} // "cgo_export_static" symbols
|
||||||
generatedSyms map[Sym]struct{} // symbols that generate their content
|
|
||||||
|
|
||||||
// Outer and Sub relations for symbols.
|
// Outer and Sub relations for symbols.
|
||||||
// TODO: figure out whether it's more efficient to just have these
|
outer []Sym // indexed by global index
|
||||||
// as fields on extSymPayload (note that this won't be a viable
|
|
||||||
// strategy if somewhere in the linker we set sub/outer for a
|
|
||||||
// non-external sym).
|
|
||||||
outer map[Sym]Sym
|
|
||||||
sub map[Sym]Sym
|
sub map[Sym]Sym
|
||||||
|
|
||||||
dynimplib map[Sym]string // stores Dynimplib symbol attribute
|
dynimplib map[Sym]string // stores Dynimplib symbol attribute
|
||||||
@ -318,7 +314,6 @@ func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorRepor
|
|||||||
extReader: extReader,
|
extReader: extReader,
|
||||||
symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols
|
symsByName: [2]map[string]Sym{make(map[string]Sym, 80000), make(map[string]Sym, 50000)}, // preallocate ~2MB for ABI0 and ~1MB for ABI1 symbols
|
||||||
objByPkg: make(map[string]uint32),
|
objByPkg: make(map[string]uint32),
|
||||||
outer: make(map[Sym]Sym),
|
|
||||||
sub: make(map[Sym]Sym),
|
sub: make(map[Sym]Sym),
|
||||||
dynimplib: make(map[Sym]string),
|
dynimplib: make(map[Sym]string),
|
||||||
dynimpvers: make(map[Sym]string),
|
dynimpvers: make(map[Sym]string),
|
||||||
@ -332,10 +327,8 @@ func NewLoader(flags uint32, elfsetstring elfsetstringFunc, reporter *ErrorRepor
|
|||||||
plt: make(map[Sym]int32),
|
plt: make(map[Sym]int32),
|
||||||
got: make(map[Sym]int32),
|
got: make(map[Sym]int32),
|
||||||
dynid: make(map[Sym]int32),
|
dynid: make(map[Sym]int32),
|
||||||
attrSpecial: make(map[Sym]struct{}),
|
|
||||||
attrCgoExportDynamic: make(map[Sym]struct{}),
|
attrCgoExportDynamic: make(map[Sym]struct{}),
|
||||||
attrCgoExportStatic: make(map[Sym]struct{}),
|
attrCgoExportStatic: make(map[Sym]struct{}),
|
||||||
generatedSyms: make(map[Sym]struct{}),
|
|
||||||
deferReturnTramp: make(map[Sym]bool),
|
deferReturnTramp: make(map[Sym]bool),
|
||||||
extStaticSyms: make(map[nameVer]Sym),
|
extStaticSyms: make(map[nameVer]Sym),
|
||||||
builtinSyms: make([]Sym, nbuiltin),
|
builtinSyms: make([]Sym, nbuiltin),
|
||||||
@ -496,6 +489,7 @@ func (l *Loader) newExtSym(name string, ver int) Sym {
|
|||||||
l.extStart = i
|
l.extStart = i
|
||||||
}
|
}
|
||||||
l.growValues(int(i) + 1)
|
l.growValues(int(i) + 1)
|
||||||
|
l.growOuter(int(i) + 1)
|
||||||
l.growAttrBitmaps(int(i) + 1)
|
l.growAttrBitmaps(int(i) + 1)
|
||||||
pi := l.newPayload(name, ver)
|
pi := l.newPayload(name, ver)
|
||||||
l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)})
|
l.objSyms = append(l.objSyms, objSym{l.extReader.objidx, uint32(pi)})
|
||||||
@ -1010,17 +1004,16 @@ func (l *Loader) SetAttrExternal(i Sym, v bool) {
|
|||||||
// address (i.e. Value) computed by the usual mechanism of
|
// address (i.e. Value) computed by the usual mechanism of
|
||||||
// data.go:dodata() & data.go:address().
|
// data.go:dodata() & data.go:address().
|
||||||
func (l *Loader) AttrSpecial(i Sym) bool {
|
func (l *Loader) AttrSpecial(i Sym) bool {
|
||||||
_, ok := l.attrSpecial[i]
|
return l.attrSpecial.Has(i)
|
||||||
return ok
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetAttrSpecial sets the "special" property for a symbol (see
|
// SetAttrSpecial sets the "special" property for a symbol (see
|
||||||
// AttrSpecial).
|
// AttrSpecial).
|
||||||
func (l *Loader) SetAttrSpecial(i Sym, v bool) {
|
func (l *Loader) SetAttrSpecial(i Sym, v bool) {
|
||||||
if v {
|
if v {
|
||||||
l.attrSpecial[i] = struct{}{}
|
l.attrSpecial.Set(i)
|
||||||
} else {
|
} else {
|
||||||
delete(l.attrSpecial, i)
|
l.attrSpecial.Unset(i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1072,8 +1065,10 @@ func (l *Loader) SetAttrCgoExportStatic(i Sym, v bool) {
|
|||||||
// generator symbol through the SetIsGeneratedSym. The functions for generator
|
// generator symbol through the SetIsGeneratedSym. The functions for generator
|
||||||
// symbols are kept in the Link context.
|
// symbols are kept in the Link context.
|
||||||
func (l *Loader) IsGeneratedSym(i Sym) bool {
|
func (l *Loader) IsGeneratedSym(i Sym) bool {
|
||||||
_, ok := l.generatedSyms[i]
|
if !l.IsExternal(i) {
|
||||||
return ok
|
return false
|
||||||
|
}
|
||||||
|
return l.generatedSyms.Has(l.extIndex(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetIsGeneratedSym marks symbols as generated symbols. Data shouldn't be
|
// SetIsGeneratedSym marks symbols as generated symbols. Data shouldn't be
|
||||||
@ -1084,9 +1079,9 @@ func (l *Loader) SetIsGeneratedSym(i Sym, v bool) {
|
|||||||
panic("only external symbols can be generated")
|
panic("only external symbols can be generated")
|
||||||
}
|
}
|
||||||
if v {
|
if v {
|
||||||
l.generatedSyms[i] = struct{}{}
|
l.generatedSyms.Set(l.extIndex(i))
|
||||||
} else {
|
} else {
|
||||||
delete(l.generatedSyms, i)
|
l.generatedSyms.Unset(l.extIndex(i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1730,19 +1725,24 @@ func (l *Loader) AddInteriorSym(container Sym, interior Sym) {
|
|||||||
l.outer[interior] = container
|
l.outer[interior] = container
|
||||||
}
|
}
|
||||||
|
|
||||||
// OuterSym gets the outer symbol for host object loaded symbols.
|
// OuterSym gets the outer/container symbol.
|
||||||
func (l *Loader) OuterSym(i Sym) Sym {
|
func (l *Loader) OuterSym(i Sym) Sym {
|
||||||
// FIXME: add check for isExternal?
|
|
||||||
return l.outer[i]
|
return l.outer[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubSym gets the subsymbol for host object loaded symbols.
|
// SubSym gets the subsymbol for host object loaded symbols.
|
||||||
func (l *Loader) SubSym(i Sym) Sym {
|
func (l *Loader) SubSym(i Sym) Sym {
|
||||||
// NB: note -- no check for l.isExternal(), since I am pretty sure
|
|
||||||
// that later phases in the linker set subsym for "type:" syms
|
|
||||||
return l.sub[i]
|
return l.sub[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// growOuter grows the slice used to store outer symbol.
|
||||||
|
func (l *Loader) growOuter(reqLen int) {
|
||||||
|
curLen := len(l.outer)
|
||||||
|
if reqLen > curLen {
|
||||||
|
l.outer = append(l.outer, make([]Sym, reqLen-curLen)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SetCarrierSym declares that 'c' is the carrier or container symbol
|
// SetCarrierSym declares that 'c' is the carrier or container symbol
|
||||||
// for 's'. Carrier symbols are used in the linker to as a container
|
// for 's'. Carrier symbols are used in the linker to as a container
|
||||||
// for a collection of sub-symbols where the content of the
|
// for a collection of sub-symbols where the content of the
|
||||||
@ -1835,6 +1835,7 @@ func (l *Loader) growAttrBitmaps(reqLen int) {
|
|||||||
l.attrLocal = growBitmap(reqLen, l.attrLocal)
|
l.attrLocal = growBitmap(reqLen, l.attrLocal)
|
||||||
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
|
l.attrNotInSymbolTable = growBitmap(reqLen, l.attrNotInSymbolTable)
|
||||||
l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface)
|
l.attrUsedInIface = growBitmap(reqLen, l.attrUsedInIface)
|
||||||
|
l.attrSpecial = growBitmap(reqLen, l.attrSpecial)
|
||||||
}
|
}
|
||||||
l.growExtAttrBitmaps()
|
l.growExtAttrBitmaps()
|
||||||
}
|
}
|
||||||
@ -1847,6 +1848,7 @@ func (l *Loader) growExtAttrBitmaps() {
|
|||||||
l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
|
l.attrDuplicateOK = growBitmap(extReqLen, l.attrDuplicateOK)
|
||||||
l.attrShared = growBitmap(extReqLen, l.attrShared)
|
l.attrShared = growBitmap(extReqLen, l.attrShared)
|
||||||
l.attrExternal = growBitmap(extReqLen, l.attrExternal)
|
l.attrExternal = growBitmap(extReqLen, l.attrExternal)
|
||||||
|
l.generatedSyms = growBitmap(extReqLen, l.generatedSyms)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2219,6 +2221,7 @@ func (l *Loader) LoadSyms(arch *sys.Arch) {
|
|||||||
loadObjRefs(l, o.r, arch)
|
loadObjRefs(l, o.r, arch)
|
||||||
}
|
}
|
||||||
l.values = make([]int64, l.NSym(), l.NSym()+1000) // +1000 make some room for external symbols
|
l.values = make([]int64, l.NSym(), l.NSym()+1000) // +1000 make some room for external symbols
|
||||||
|
l.outer = make([]Sym, l.NSym(), l.NSym()+1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
|
func loadObjRefs(l *Loader, r *oReader, arch *sys.Arch) {
|
||||||
|
Loading…
Reference in New Issue
Block a user