Commit 86da989e authored by Dmitriy Vyukov's avatar Dmitriy Vyukov

runtime: introduce helper persistentalloc() function

It is a caching wrapper around SysAlloc() that can allocate small chunks.
Use it for symtab allocations. Reduces number of symtab walks from 4 to 3
(reduces buildfuncs time from 10ms to 7.5ms on a large binary,
reduces initial heap size by 680K on the same binary).
Also can be used for type info allocation, itab allocation.
There are also several places in GC where we do the same thing,
they can be changed to use persistentalloc().
Also can be used in FixAlloc, because each instance of FixAlloc allocates
in 128K regions, which is too eager.
Reincarnation of committed and rolled back https://golang.org/cl/9805043
The latent bugs that it revealed are fixed:
https://golang.org/cl/9837049
https://golang.org/cl/9778048

R=golang-dev, khr
CC=golang-dev
https://golang.org/cl/9778049
parent d6f89d73
...@@ -498,6 +498,53 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n) ...@@ -498,6 +498,53 @@ runtime·MHeap_SysAlloc(MHeap *h, uintptr n)
return p; return p;
} }
static struct
{
Lock;
byte* pos;
byte* end;
} persistent;
enum
{
PersistentAllocChunk = 256<<10,
PersistentAllocMaxBlock = 64<<10, // VM reservation granularity is 64K on windows
};
// Wrapper around SysAlloc that can allocate small chunks.
// There is no associated free operation.
// Intended for things like function/type/debug-related persistent data.
// If align is 0, uses default align (currently 8).
void*
runtime·persistentalloc(uintptr size, uintptr align)
{
byte *p;
if(align) {
if(align&(align-1))
runtime·throw("persistentalloc: align is now a power of 2");
if(align > PageSize)
runtime·throw("persistentalloc: align is too large");
} else
align = 8;
if(size >= PersistentAllocMaxBlock)
return runtime·SysAlloc(size);
runtime·lock(&persistent);
persistent.pos = (byte*)ROUND((uintptr)persistent.pos, align);
if(persistent.pos + size > persistent.end) {
persistent.pos = runtime·SysAlloc(PersistentAllocChunk);
if(persistent.pos == nil) {
runtime·unlock(&persistent);
runtime·throw("runtime: cannot allocate memory");
}
persistent.end = persistent.pos + PersistentAllocChunk;
}
p = persistent.pos;
persistent.pos += size;
runtime·unlock(&persistent);
return p;
}
static Lock settype_lock; static Lock settype_lock;
void void
......
...@@ -447,6 +447,7 @@ void runtime·MHeap_MapSpans(MHeap *h); ...@@ -447,6 +447,7 @@ void runtime·MHeap_MapSpans(MHeap *h);
void runtime·MHeap_Scavenger(void); void runtime·MHeap_Scavenger(void);
void* runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed); void* runtime·mallocgc(uintptr size, uint32 flag, int32 dogc, int32 zeroed);
void* runtime·persistentalloc(uintptr size, uintptr align);
int32 runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **s); int32 runtime·mlookup(void *v, byte **base, uintptr *size, MSpan **s);
void runtime·gc(int32 force); void runtime·gc(int32 force);
void runtime·markallocated(void *v, uintptr n, bool noptr); void runtime·markallocated(void *v, uintptr n, bool noptr);
......
...@@ -69,11 +69,6 @@ struct Sym ...@@ -69,11 +69,6 @@ struct Sym
static uintptr mainoffset; static uintptr mainoffset;
// A dynamically allocated string containing multiple substrings.
// Individual strings are slices of hugestring.
static String hugestring;
static int32 hugestring_len;
extern void main·main(void); extern void main·main(void);
static uintptr static uintptr
...@@ -303,7 +298,6 @@ makepath(byte *buf, int32 nbuf, byte *path) ...@@ -303,7 +298,6 @@ makepath(byte *buf, int32 nbuf, byte *path)
return p - buf; return p - buf;
} }
// appends p to hugestring
static String static String
gostringn(byte *p, int32 l) gostringn(byte *p, int32 l)
{ {
...@@ -311,13 +305,8 @@ gostringn(byte *p, int32 l) ...@@ -311,13 +305,8 @@ gostringn(byte *p, int32 l)
if(l == 0) if(l == 0)
return runtime·emptystring; return runtime·emptystring;
if(hugestring.str == nil) {
hugestring_len += l;
return runtime·emptystring;
}
s.str = hugestring.str + hugestring.len;
s.len = l; s.len = l;
hugestring.len += s.len; s.str = runtime·persistentalloc(l, 1);
runtime·memmove(s.str, p, l); runtime·memmove(s.str, p, l);
return s; return s;
} }
...@@ -348,8 +337,6 @@ dosrcline(Sym *sym) ...@@ -348,8 +337,6 @@ dosrcline(Sym *sym)
switch(sym->symtype) { switch(sym->symtype) {
case 't': case 't':
case 'T': case 'T':
if(hugestring.str == nil)
break;
if(runtime·strcmp(sym->name, (byte*)"etext") == 0) if(runtime·strcmp(sym->name, (byte*)"etext") == 0)
break; break;
f = &func[nfunc++]; f = &func[nfunc++];
...@@ -574,11 +561,12 @@ runtime·symtabinit(void) ...@@ -574,11 +561,12 @@ runtime·symtabinit(void)
walksymtab(dofunc); walksymtab(dofunc);
// Initialize tables. // Initialize tables.
// Can use FlagNoPointers - all pointers either point into sections of the executable // Memory obtained from runtime·persistentalloc() is not scanned by GC,
// or point into hugestring. // this is fine because all pointers either point into sections of the executable
func = runtime·mallocgc((nfunc+1)*sizeof func[0], FlagNoPointers, 0, 1); // or also obtained from persistentmalloc().
func = runtime·persistentalloc((nfunc+1)*sizeof func[0], 0);
func[nfunc].entry = (uint64)etext; func[nfunc].entry = (uint64)etext;
fname = runtime·mallocgc(nfname*sizeof fname[0], FlagNoPointers, 0, 1); fname = runtime·persistentalloc(nfname*sizeof fname[0], 0);
nfunc = 0; nfunc = 0;
lastvalue = 0; lastvalue = 0;
walksymtab(dofunc); walksymtab(dofunc);
...@@ -588,15 +576,9 @@ runtime·symtabinit(void) ...@@ -588,15 +576,9 @@ runtime·symtabinit(void)
// record src file and line info for each func // record src file and line info for each func
files = runtime·malloc(maxfiles * sizeof(files[0])); files = runtime·malloc(maxfiles * sizeof(files[0]));
walksymtab(dosrcline); // pass 1: determine hugestring_len walksymtab(dosrcline);
hugestring.str = runtime·mallocgc(hugestring_len, FlagNoPointers, 0, 0);
hugestring.len = 0;
walksymtab(dosrcline); // pass 2: fill and use hugestring
files = nil; files = nil;
if(hugestring.len != hugestring_len)
runtime·throw("buildfunc: problem in initialization procedure");
m->nomemprof--; m->nomemprof--;
} }
......
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