mirror of
https://github.com/golang/go
synced 2024-11-12 10:30:23 -07:00
runtime: make NumGoroutines faster
Resolves TODO for not walking all goroutines in NumGoroutines. LGTM=khr R=golang-codereviews, khr CC=golang-codereviews, rsc https://golang.org/cl/107290044
This commit is contained in:
parent
dc84eca75e
commit
92c1e72040
@ -47,6 +47,7 @@ struct Sched {
|
|||||||
// Global cache of dead G's.
|
// Global cache of dead G's.
|
||||||
Lock gflock;
|
Lock gflock;
|
||||||
G* gfree;
|
G* gfree;
|
||||||
|
int32 ngfree;
|
||||||
|
|
||||||
uint32 gcwaiting; // gc is waiting to run
|
uint32 gcwaiting; // gc is waiting to run
|
||||||
int32 stopwait;
|
int32 stopwait;
|
||||||
@ -1964,6 +1965,7 @@ gfput(P *p, G *gp)
|
|||||||
p->gfree = gp->schedlink;
|
p->gfree = gp->schedlink;
|
||||||
gp->schedlink = runtime·sched.gfree;
|
gp->schedlink = runtime·sched.gfree;
|
||||||
runtime·sched.gfree = gp;
|
runtime·sched.gfree = gp;
|
||||||
|
runtime·sched.ngfree++;
|
||||||
}
|
}
|
||||||
runtime·unlock(&runtime·sched.gflock);
|
runtime·unlock(&runtime·sched.gflock);
|
||||||
}
|
}
|
||||||
@ -1981,10 +1983,11 @@ retry:
|
|||||||
gp = p->gfree;
|
gp = p->gfree;
|
||||||
if(gp == nil && runtime·sched.gfree) {
|
if(gp == nil && runtime·sched.gfree) {
|
||||||
runtime·lock(&runtime·sched.gflock);
|
runtime·lock(&runtime·sched.gflock);
|
||||||
while(p->gfreecnt < 32 && runtime·sched.gfree) {
|
while(p->gfreecnt < 32 && runtime·sched.gfree != nil) {
|
||||||
p->gfreecnt++;
|
p->gfreecnt++;
|
||||||
gp = runtime·sched.gfree;
|
gp = runtime·sched.gfree;
|
||||||
runtime·sched.gfree = gp->schedlink;
|
runtime·sched.gfree = gp->schedlink;
|
||||||
|
runtime·sched.ngfree--;
|
||||||
gp->schedlink = p->gfree;
|
gp->schedlink = p->gfree;
|
||||||
p->gfree = gp;
|
p->gfree = gp;
|
||||||
}
|
}
|
||||||
@ -2022,12 +2025,13 @@ gfpurge(P *p)
|
|||||||
G *gp;
|
G *gp;
|
||||||
|
|
||||||
runtime·lock(&runtime·sched.gflock);
|
runtime·lock(&runtime·sched.gflock);
|
||||||
while(p->gfreecnt) {
|
while(p->gfreecnt != 0) {
|
||||||
p->gfreecnt--;
|
p->gfreecnt--;
|
||||||
gp = p->gfree;
|
gp = p->gfree;
|
||||||
p->gfree = gp->schedlink;
|
p->gfree = gp->schedlink;
|
||||||
gp->schedlink = runtime·sched.gfree;
|
gp->schedlink = runtime·sched.gfree;
|
||||||
runtime·sched.gfree = gp;
|
runtime·sched.gfree = gp;
|
||||||
|
runtime·sched.ngfree++;
|
||||||
}
|
}
|
||||||
runtime·unlock(&runtime·sched.gflock);
|
runtime·unlock(&runtime·sched.gflock);
|
||||||
}
|
}
|
||||||
@ -2136,23 +2140,16 @@ runtime·lockedOSThread(void)
|
|||||||
int32
|
int32
|
||||||
runtime·gcount(void)
|
runtime·gcount(void)
|
||||||
{
|
{
|
||||||
G *gp;
|
P *p, **pp;
|
||||||
int32 n, s;
|
int32 n;
|
||||||
uintptr i;
|
|
||||||
|
|
||||||
n = 0;
|
n = runtime·allglen - runtime·sched.ngfree;
|
||||||
runtime·lock(&allglock);
|
for(pp=runtime·allp; p=*pp; pp++)
|
||||||
// TODO(dvyukov): runtime.NumGoroutine() is O(N).
|
n -= p->gfreecnt;
|
||||||
// We do not want to increment/decrement centralized counter in newproc/goexit,
|
// All these variables can be changed concurrently, so the result can be inconsistent.
|
||||||
// just to make runtime.NumGoroutine() faster.
|
// But at least the current goroutine is running.
|
||||||
// Compromise solution is to introduce per-P counters of active goroutines.
|
if(n < 1)
|
||||||
for(i = 0; i < runtime·allglen; i++) {
|
n = 1;
|
||||||
gp = runtime·allg[i];
|
|
||||||
s = gp->status;
|
|
||||||
if(s == Grunnable || s == Grunning || s == Gsyscall || s == Gwaiting)
|
|
||||||
n++;
|
|
||||||
}
|
|
||||||
runtime·unlock(&allglock);
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user