/* * This is a test program to reproduce a scheduling oddity I have found. * * (c) Balazs Scheidler * * Pass any argument to the program to set the CPU affinity. */ #define _GNU_SOURCE #include #include #include #include #include #include /* diff in millisecs */ long tv_diff(struct timeval *t1, struct timeval *t2) { long long diff = (t2->tv_sec - t1->tv_sec) * 1e9 + (t2->tv_usec - t1->tv_usec); return diff / 1e6; } int reader(int fd) { char buf[4096]; int i; while (read(fd, buf, sizeof(buf)) > 0) { for (i = 0; i < 20000; i++) memset(buf, 'A'+i, sizeof(buf)); } return 0; } int writer(int fd) { char buf[4096]; int i; int counter, prev_counter; struct timeval start, end, prev, now; long diff; memset(buf, 'A', sizeof(buf)); counter = 0; prev_counter = 0; gettimeofday(&start, NULL); /* feed the other process with data while doing something that spins the CPU */ while (write(fd, buf, sizeof(buf)) > 0) { for (i = 0; i < 100000; i++) memset(buf, 'A'+i, sizeof(buf)); /* the rest of the loop is only to measure performance */ counter++; gettimeofday(&now, NULL); if (now.tv_sec != prev.tv_sec) { diff = tv_diff(&prev, &now); printf("Check: %ld loops/sec, sum: %d \n", ((counter - prev_counter) * 1000) / diff, counter); prev_counter = counter; } if (now.tv_sec - start.tv_sec > 20) break; prev = now; } gettimeofday(&end, NULL); diff = tv_diff(&start, &end); printf("Final: %ld loops/sec, sum: %d\n", (counter*1000) / diff, counter); return 0; } int main(int argc, char *argv) { int fds[2]; cpu_set_t s; int set_affinity = 0; CPU_ZERO(&s); if (argc > 1) set_affinity = 1; pipe(fds); if (fork() == 0) { if (set_affinity) { CPU_SET(0, &s); sched_setaffinity(getpid(), sizeof(s), &s); } close(fds[1]); reader(fds[0]); return 0; } if (set_affinity) { CPU_SET(1, &s); sched_setaffinity(getpid(), sizeof(s), &s); } close(fds[0]); writer(fds[1]); }