Skip to content

Commit a69fc0b

Browse files
committed
Initial import.
0 parents  commit a69fc0b

File tree

7 files changed

+312
-0
lines changed

7 files changed

+312
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
timectxsw
2+
timectxswws
3+
timesyscall
4+
timetctxsw

Makefile

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CC = gcc
2+
CFLAGS = -mtune=native -O3 -D_XOPEN_SOURCE=600 -D_GNU_SOURCE -std=c99 \
3+
-W -Wall -Werror
4+
LDFLAGS = -lrt
5+
6+
all: bench
7+
8+
bench: timectxsw timectxswws timesyscall timetctxsw
9+
./cpubench.sh
10+
11+
.PHONY: all bench

cpubench.sh

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/bin/bash
2+
fgrep 'model name' /proc/cpuinfo | sort -u | xargs
3+
pgrep vmware >/dev/null && echo Running under VMware
4+
ncpus=`sort -u /sys/devices/system/cpu/cpu*/topology/physical_package_id | wc -l`
5+
corepercpu=`sort -u /sys/devices/system/cpu/cpu*/topology/core_id | wc -l`
6+
threadpercore=`sed \
7+
"s/2/10/g;\
8+
s/3/11/g;\
9+
s/4/100/g;\
10+
s/5/101/g;\
11+
s/6/110/g;\
12+
s/7/111/g;\
13+
s/8/1000/g;\
14+
s/9/1001/g;\
15+
s/a/1010/g;\
16+
s/b/1011/g;\
17+
s/c/1100/g;\
18+
s/d/1101/g;\
19+
s/e/1110/g;\
20+
s/f/1111/g;\
21+
s/[^1]//g" /sys/devices/system/cpu/cpu*/topology/thread_siblings \
22+
| while read nthreads; do echo ${#nthreads}; done | sort -u`
23+
total=$((ncpus * corepercpu * threadpercore))
24+
echo "$ncpus physical CPUs, $corepercpu cores/CPU,\
25+
$threadpercore hardware threads/core = $total hw threads total"
26+
27+
runbench() {
28+
$* ./timesyscall
29+
$* ./timectxsw
30+
$* ./timetctxsw
31+
}
32+
33+
echo '-- No CPU affinity --'
34+
runbench
35+
36+
echo '-- With CPU affinity --'
37+
runbench taskset -c $((total - 1))

timectxsw.c

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#include <sched.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <sys/ipc.h>
5+
#include <sys/shm.h>
6+
#include <sys/syscall.h>
7+
#include <sys/wait.h>
8+
#include <time.h>
9+
#include <unistd.h>
10+
11+
#include <linux/futex.h>
12+
13+
static inline long long unsigned time_ns(struct timespec* const ts) {
14+
if (clock_gettime(CLOCK_REALTIME, ts)) {
15+
exit(1);
16+
}
17+
return ((long long unsigned) ts->tv_sec) * 1000000000LLU
18+
+ (long long unsigned) ts->tv_nsec;
19+
}
20+
21+
int main(void) {
22+
const int iterations = 500000;
23+
struct timespec ts;
24+
const int shm_id = shmget(IPC_PRIVATE, sizeof (int), IPC_CREAT | 0666);
25+
const pid_t other = fork();
26+
int* futex = shmat(shm_id, NULL, 0);
27+
*futex = 0xA;
28+
if (other == 0) {
29+
for (int i = 0; i < iterations; i++) {
30+
sched_yield();
31+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xA, NULL, NULL, 42)) {
32+
// retry
33+
sched_yield();
34+
}
35+
*futex = 0xB;
36+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
37+
// retry
38+
sched_yield();
39+
}
40+
}
41+
return 0;
42+
}
43+
44+
const long long unsigned start_ns = time_ns(&ts);
45+
for (int i = 0; i < iterations; i++) {
46+
*futex = 0xA;
47+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
48+
// retry
49+
sched_yield();
50+
}
51+
sched_yield();
52+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xB, NULL, NULL, 42)) {
53+
// retry
54+
sched_yield();
55+
}
56+
}
57+
const long long unsigned delta = time_ns(&ts) - start_ns;
58+
59+
const int nswitches = iterations << 2;
60+
printf("%i process context switches in %lluns (%.1fns/ctxsw)\n",
61+
nswitches, delta, (delta / (float) nswitches));
62+
wait(futex);
63+
return 0;
64+
}

timectxswws.c

+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#include <sched.h>
2+
#include <stdio.h>
3+
#include <stdlib.h>
4+
#include <string.h>
5+
#include <sys/ipc.h>
6+
#include <sys/shm.h>
7+
#include <sys/syscall.h>
8+
#include <sys/wait.h>
9+
#include <time.h>
10+
#include <unistd.h>
11+
12+
#include <linux/futex.h>
13+
14+
static inline long long unsigned time_ns(struct timespec* const ts) {
15+
if (clock_gettime(CLOCK_REALTIME, ts)) {
16+
exit(1);
17+
}
18+
return ((long long unsigned) ts->tv_sec) * 1000000000LLU
19+
+ (long long unsigned) ts->tv_nsec;
20+
}
21+
22+
int main(int argc, char** argv) {
23+
if (argc != 2) {
24+
fprintf(stderr, "usage: %s <size of working set in 4K pages>\n", *argv);
25+
return 1;
26+
}
27+
const long ws_pages = strtol(argv[1], NULL, 10);
28+
if (ws_pages < 0) {
29+
fprintf(stderr, "Invalid usage: working set size must be positive\n");
30+
return 1;
31+
}
32+
const int iterations = 20000;
33+
struct timespec ts;
34+
35+
long long unsigned memset_time = 0;
36+
if (ws_pages) {
37+
void* buf = malloc(ws_pages * 4096);
38+
memset_time = time_ns(&ts);
39+
for (int i = 0; i < iterations; i++) {
40+
memset(buf, i, ws_pages * 4096);
41+
}
42+
memset_time = time_ns(&ts) - memset_time;
43+
printf("%i memset on %4liK in %10lluns (%.1fns/page)\n",
44+
iterations, ws_pages * 4, memset_time,
45+
(memset_time / ((float) ws_pages * iterations)));
46+
free(buf);
47+
}
48+
49+
const int shm_id = shmget(IPC_PRIVATE, sizeof (int) + ws_pages * 4096,
50+
IPC_CREAT | 0666);
51+
const pid_t other = fork();
52+
int* futex = shmat(shm_id, NULL, 0);
53+
void* ws = futex + 1;
54+
*futex = 0xA;
55+
if (other == 0) {
56+
for (int i = 0; i < iterations; i++) {
57+
sched_yield();
58+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xA, NULL, NULL, 42)) {
59+
// retry
60+
sched_yield();
61+
}
62+
*futex = 0xB;
63+
if (ws_pages) {
64+
memset(ws, i, ws_pages * 4096);
65+
}
66+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
67+
// retry
68+
sched_yield();
69+
}
70+
}
71+
return 0;
72+
}
73+
74+
const long long unsigned start_ns = time_ns(&ts);
75+
for (int i = 0; i < iterations; i++) {
76+
*futex = 0xA;
77+
if (ws_pages) {
78+
memset(ws, i, ws_pages * 4096);
79+
}
80+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
81+
// retry
82+
sched_yield();
83+
}
84+
sched_yield();
85+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xB, NULL, NULL, 42)) {
86+
// retry
87+
sched_yield();
88+
}
89+
}
90+
const long long unsigned delta = time_ns(&ts) - start_ns - memset_time * 2;
91+
92+
const int nswitches = iterations * 4;
93+
printf("%i process context switches (wss:%4liK) in %12lluns (%.1fns/ctxsw)\n",
94+
nswitches, ws_pages * 4, delta, (delta / (float) nswitches));
95+
wait(futex);
96+
return 0;
97+
}

timesyscall.c

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <sys/syscall.h>
4+
#include <time.h>
5+
#include <unistd.h>
6+
7+
static inline long long unsigned time_ns(struct timespec* const ts) {
8+
if (clock_gettime(CLOCK_REALTIME, ts)) {
9+
exit(1);
10+
}
11+
return ((long long unsigned) ts->tv_sec) * 1000000000LLU
12+
+ (long long unsigned) ts->tv_nsec;
13+
}
14+
15+
int main(void) {
16+
const int iterations = 10000000;
17+
struct timespec ts;
18+
const long long unsigned start_ns = time_ns(&ts);
19+
for (int i = 0; i < iterations; i++) {
20+
if (syscall(SYS_gettid) <= 1) {
21+
exit(2);
22+
}
23+
}
24+
const long long unsigned delta = time_ns(&ts) - start_ns;
25+
printf("%i system calls in %lluns (%.1fns/syscall)\n",
26+
iterations, delta, (delta / (float) iterations));
27+
return 0;
28+
}

timetctxsw.c

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#include <pthread.h>
2+
#include <sched.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <sys/ipc.h>
6+
#include <sys/shm.h>
7+
#include <sys/syscall.h>
8+
#include <sys/wait.h>
9+
#include <time.h>
10+
#include <unistd.h>
11+
12+
#include <linux/futex.h>
13+
14+
static inline long long unsigned time_ns(struct timespec* const ts) {
15+
if (clock_gettime(CLOCK_REALTIME, ts)) {
16+
exit(1);
17+
}
18+
return ((long long unsigned) ts->tv_sec) * 1000000000LLU
19+
+ (long long unsigned) ts->tv_nsec;
20+
}
21+
22+
static const int iterations = 500000;
23+
24+
static void* thread(void* restrict ftx) {
25+
int* futex = (int*) ftx;
26+
for (int i = 0; i < iterations; i++) {
27+
sched_yield();
28+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xA, NULL, NULL, 42)) {
29+
// retry
30+
sched_yield();
31+
}
32+
*futex = 0xB;
33+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
34+
// retry
35+
sched_yield();
36+
}
37+
}
38+
return NULL;
39+
}
40+
41+
int main(void) {
42+
struct timespec ts;
43+
const int shm_id = shmget(IPC_PRIVATE, sizeof (int), IPC_CREAT | 0666);
44+
int* futex = shmat(shm_id, NULL, 0);
45+
pthread_t thd;
46+
if (pthread_create(&thd, NULL, thread, futex)) {
47+
return 1;
48+
}
49+
*futex = 0xA;
50+
51+
const long long unsigned start_ns = time_ns(&ts);
52+
for (int i = 0; i < iterations; i++) {
53+
*futex = 0xA;
54+
while (!syscall(SYS_futex, futex, FUTEX_WAKE, 1, NULL, NULL, 42)) {
55+
// retry
56+
sched_yield();
57+
}
58+
sched_yield();
59+
while (syscall(SYS_futex, futex, FUTEX_WAIT, 0xB, NULL, NULL, 42)) {
60+
// retry
61+
sched_yield();
62+
}
63+
}
64+
const long long unsigned delta = time_ns(&ts) - start_ns;
65+
66+
const int nswitches = iterations << 2;
67+
printf("%i thread context switches in %lluns (%.1fns/ctxsw)\n",
68+
nswitches, delta, (delta / (float) nswitches));
69+
wait(futex);
70+
return 0;
71+
}

0 commit comments

Comments
 (0)