123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- /*
- * 1. Measure the cost of system call
- * about 0.6 clock tick (us)
- * 2. Measure the context switch
- * about 25 clock tick (us)
- * but when affinity is set to same CPU
- * it is reduced to 7/6/10 (us)
- */
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/wait.h>
- #include <sys/time.h>
- #include <fcntl.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdint.h>
- #include <inttypes.h>
- #include <time.h>
- #define _GNU_SOURCE
- #define __USE_GNU
- #include <sched.h>
- static const char* dir_path = "dummy";
- #define COUNTER 1000
- /*
- Abstraction
- */
- typedef uint64_t (*get_time_func)(void);
- typedef void (*print_time_func)(uint64_t);
- struct time_counter
- {
- /* private */
- get_time_func __get_time;
- print_time_func __print_time;
- uint64_t __time;
- };
- static void
- time_counter_start(struct time_counter* counter)
- {
- counter->__time = counter->__get_time();
- }
- static void
- time_counter_stop(struct time_counter* counter)
- {
- uint64_t time = counter->__get_time();
- counter->__time = time - counter->__time;
- }
- static void
- time_counter_print(const struct time_counter* counter)
- {
- counter->__print_time(counter->__time);
- }
- /*
- * gettimeofday implementation
- */
- static uint64_t
- gettimeofday_get_time(void)
- {
- struct timeval tv;
- if (gettimeofday(&tv, NULL) == -1)
- {
- exit(EXIT_FAILURE);
- }
- /* ignore seconds */
- return tv.tv_usec;
- }
- static void
- gettimeofday_print_time(uint64_t time)
- {
- printf("gettimeofday: %" PRIu64 " us\n", time);
- }
- /*
- * read time stamp counter implementation
- */
- static uint64_t
- rdtsc_get_time(void)
- {
- uint32_t hi, lo;
- asm("rdtsc"
- : "=a" (lo), "=d" (hi));
- return (uint64_t)hi << 32 | lo;
- }
- static void
- tick_print_time(uint64_t time)
- {
- int usec_res = CLOCKS_PER_SEC / 1000000;
- printf("ticks: %" PRIu64 " ticks | resolution: %d clock tick per us\n",
- time,
- usec_res);
- }
- /*
- * clock glibc implementation
- */
- static uint64_t
- clock_get_time(void)
- {
- return clock();
- }
- /* system call function */
- volatile static void
- call_system_call(size_t syscall_num)
- {
- int fd;
- if ((fd = open(dir_path, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) == -1)
- {
- perror("cannot open file");
- exit(EXIT_FAILURE);
- }
- size_t counter = syscall_num;
- char *buff;
- while (counter--)
- {
- read(fd, buff, 0);
- }
- close(fd);
- }
- /* factory method */
- enum measurement_method
- {
- gettimeofday_method,
- rdtsc_method,
- clock_method,
- };
- static struct time_counter
- obtain_counter(enum measurement_method method)
- {
- struct time_counter counter;
- switch(method)
- {
- case gettimeofday_method:
- counter.__get_time = gettimeofday_get_time;
- counter.__print_time = gettimeofday_print_time;
- break;
- case rdtsc_method:
- counter.__get_time = rdtsc_get_time;
- counter.__print_time = tick_print_time;
- break;
- case clock_method:
- counter.__get_time = clock_get_time;
- counter.__print_time = tick_print_time;
- break;
- default:
- fprintf(stderr, "measurement method not supported!\n");
- exit(EXIT_FAILURE);
- }
- counter.__time = 0;
- return counter;
- }
- static void
- print_cpu_affinity(void)
- {
- printf("CPU: %d\n", sched_getcpu());
- }
- static void
- place_on_single_cpu(int cpu, pid_t pid)
- {
- cpu_set_t cpuset;
- CPU_ZERO(&cpuset);
- CPU_SET(cpu, &cpuset);
- sched_setaffinity(pid, CPU_SETSIZE, &cpuset);
- }
- int
- main(void)
- {
- place_on_single_cpu(sched_getcpu(), getpid());
- struct time_counter counter = obtain_counter(clock_method);
- /* measure system call */
- time_counter_start(&counter);
- call_system_call(COUNTER);
- time_counter_stop(&counter);
- printf("measure %dx system call\n", COUNTER);
- time_counter_print(&counter);
- puts("");
- /* measure context switch */
- int pipefd[2];
- if (pipe(pipefd) == -1) {
- perror("pipe");
- exit(EXIT_FAILURE);
- }
- int rc;
- const char *dummy_text = "switched context";
- if ((rc = fork()) == 0) {
- print_cpu_affinity();
- close(pipefd[0]);
- write(pipefd[1], dummy_text, strlen(dummy_text));
- exit(EXIT_SUCCESS);
- }
- print_cpu_affinity();
- close(pipefd[1]);
- char buffer[100];
- ssize_t bytes;
- puts("measure context switch");
- time_counter_start(&counter);
- while ((bytes = read(pipefd[0], buffer, 100)) > 0)
- {
- time_counter_stop(&counter);
- buffer[bytes] = '\0';
- printf("msg receivd: %s\n", buffer);
- }
- time_counter_print(&counter);
- wait(NULL);
- return EXIT_SUCCESS;
- }
|