a scheduler benchmark that is simpler to analyze

上级 94a5fb99
...@@ -8,43 +8,50 @@ ...@@ -8,43 +8,50 @@
static volatile std::atomic<u64> waiting; static volatile std::atomic<u64> waiting;
static volatile std::atomic<u64> waking; static volatile std::atomic<u64> waking;
static volatile u64 ftx;
static int iters; static int iters;
static int nworkers; static int nworkers;
static struct {
u64 mem;
__padout__;
} ftx[256] __mpalign__;
static static
void* worker(void* x) void* worker0(void* x)
{ {
// Ping pong a futex between a pair of workers
u64 id = (u64)x;
u64* f = &(ftx[id>>1].mem);
long r; long r;
int i;
for (i = 0; i < iters; i++) { if (id & 0x1) {
++waiting; for (u64 i = 0; i < iters; i++) {
r = futex((u64*)&ftx, FUTEX_WAIT, (u64)i, 0); r = futex(f, FUTEX_WAIT, (u64)(i<<1), 0);
if (r < 0 && r != -EWOULDBLOCK) if (r < 0 && r != -EWOULDBLOCK)
die("FUTEX_WAIT: %d", r); die("futex: %d", r);
while (waking.load() == 1) *f = (i<<1)+2;
nop_pause(); r = futex(f, FUTEX_WAKE, 1, 0);
assert(r == 0);
}
} else {
for (u64 i = 0; i < iters; i++) {
*f = (i<<1)+1;
r = futex(f, FUTEX_WAKE, 1, 0);
assert(r == 0);
r = futex(f, FUTEX_WAIT, (u64)(i<<1)+1, 0);
if (r < 0 && r != -EWOULDBLOCK)
die("futex: %d", r);
}
} }
return nullptr; return nullptr;
} }
static static
void master(void) void master0(void)
{ {
long r; for (int i = 0; i < nworkers; i++)
wait();
for (int i = 0; i < iters; i++) {
while (waiting.load() < (i+1)*nworkers)
nop_pause();
waking.store(1);
ftx = i+1;
r = futex((u64*)&ftx, FUTEX_WAKE, nworkers, 0);
assert(r == 0);
waking.store(0);
}
} }
int int
...@@ -54,7 +61,7 @@ main(int ac, char** av) ...@@ -54,7 +61,7 @@ main(int ac, char** av)
if (ac < 3) if (ac < 3)
die("usage: %s iters nworkers", av[0]); die("usage: %s iters nworkers", av[0]);
ftx = 0;
iters = atoi(av[1]); iters = atoi(av[1]);
nworkers = atoi(av[2]); nworkers = atoi(av[2]);
waiting.store(0); waiting.store(0);
...@@ -62,17 +69,53 @@ main(int ac, char** av) ...@@ -62,17 +69,53 @@ main(int ac, char** av)
for (int i = 0; i < nworkers; i++) { for (int i = 0; i < nworkers; i++) {
pthread_t th; pthread_t th;
r = pthread_create(&th, nullptr, worker, nullptr); r = pthread_create(&th, nullptr, worker0, (void*)(u64)i);
if (r < 0) if (r < 0)
die("pthread_create"); die("pthread_create");
} }
nsleep(1000*1000); nsleep(1000*1000);
u64 t0 = rdtsc(); u64 t0 = rdtsc();
master(); master0();
u64 t1 = rdtsc(); u64 t1 = rdtsc();
printf("%lu\n", (t1-t0)/iters); printf("%lu\n", (t1-t0)/iters);
}
for (int i = 0; i < nworkers; i++) #if 0
wait(); static volatile u64 ftx;
static
void* worker0(void* x)
{
long r;
int i;
for (i = 0; i < iters; i++) {
++waiting;
r = futex((u64*)&ftx, FUTEX_WAIT, (u64)i, 0);
if (r < 0 && r != -EWOULDBLOCK)
die("FUTEX_WAIT: %d", r);
while (waking.load() == 1)
nop_pause();
}
return nullptr;
}
static
void master0(void)
{
long r;
for (int i = 0; i < iters; i++) {
while (waiting.load() < (i+1)*nworkers)
nop_pause();
waking.store(1);
ftx = i+1;
r = futex((u64*)&ftx, FUTEX_WAKE, nworkers, 0);
assert(r == 0);
waking.store(0);
}
} }
#endif
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论