syscall.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. *
  3. * syscall.c
  4. *
  5. * syscall: Benchmark for system call performance
  6. */
  7. #include "../perf.h"
  8. #include "../util/util.h"
  9. #include <subcmd/parse-options.h>
  10. #include "../builtin.h"
  11. #include "bench.h"
  12. #include <stdio.h>
  13. #include <sys/time.h>
  14. #include <sys/syscall.h>
  15. #include <sys/types.h>
  16. #include <sys/wait.h>
  17. #include <unistd.h>
  18. #include <stdlib.h>
  19. #ifndef __NR_fork
  20. #define __NR_fork -1
  21. #endif
  22. static int loops;
  23. static const struct option options[] = {
  24. OPT_INTEGER('l', "loop", &loops, "Specify number of loops"),
  25. OPT_END()
  26. };
  27. static const char * const bench_syscall_usage[] = {
  28. "perf bench syscall <options>",
  29. NULL
  30. };
  31. static void test_fork(void)
  32. {
  33. pid_t pid = fork();
  34. if (pid < 0) {
  35. fprintf(stderr, "fork failed\n");
  36. exit(1);
  37. } else if (pid == 0) {
  38. exit(0);
  39. } else {
  40. if (waitpid(pid, NULL, 0) < 0) {
  41. fprintf(stderr, "waitpid failed\n");
  42. exit(1);
  43. }
  44. }
  45. }
  46. static void test_execve(void)
  47. {
  48. const char *pathname = "/bin/true";
  49. char *const argv[] = { (char *)pathname, NULL };
  50. pid_t pid = fork();
  51. if (pid < 0) {
  52. fprintf(stderr, "fork failed\n");
  53. exit(1);
  54. } else if (pid == 0) {
  55. execve(pathname, argv, NULL);
  56. fprintf(stderr, "execve /bin/true failed\n");
  57. exit(1);
  58. } else {
  59. if (waitpid(pid, NULL, 0) < 0) {
  60. fprintf(stderr, "waitpid failed\n");
  61. exit(1);
  62. }
  63. }
  64. }
  65. static int bench_syscall_common(int argc, const char **argv, int syscall)
  66. {
  67. struct timeval start, stop, diff;
  68. unsigned long long result_usec = 0;
  69. const char *name = NULL;
  70. int i;
  71. switch (syscall) {
  72. case __NR_fork:
  73. case __NR_execve:
  74. /* Limit default loop to 10000 times to save time */
  75. loops = 10000;
  76. break;
  77. default:
  78. loops = 10000000;
  79. break;
  80. }
  81. /* Options -l and --loops override default above */
  82. argc = parse_options(argc, argv, options, bench_syscall_usage, 0);
  83. gettimeofday(&start, NULL);
  84. for (i = 0; i < loops; i++) {
  85. switch (syscall) {
  86. case __NR_getppid:
  87. getppid();
  88. break;
  89. case __NR_getpgid:
  90. getpgid(0);
  91. break;
  92. case __NR_fork:
  93. test_fork();
  94. break;
  95. case __NR_execve:
  96. test_execve();
  97. default:
  98. break;
  99. }
  100. }
  101. gettimeofday(&stop, NULL);
  102. timersub(&stop, &start, &diff);
  103. switch (syscall) {
  104. case __NR_getppid:
  105. name = "getppid()";
  106. break;
  107. case __NR_getpgid:
  108. name = "getpgid()";
  109. break;
  110. case __NR_fork:
  111. name = "fork()";
  112. break;
  113. case __NR_execve:
  114. name = "execve()";
  115. break;
  116. default:
  117. break;
  118. }
  119. switch (bench_format) {
  120. case BENCH_FORMAT_DEFAULT:
  121. printf("# Executed %'d %s calls\n", loops, name);
  122. result_usec = diff.tv_sec * 1000000;
  123. result_usec += diff.tv_usec;
  124. printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
  125. (unsigned long) diff.tv_sec,
  126. (unsigned long) (diff.tv_usec/1000));
  127. printf(" %14lf usecs/op\n",
  128. (double)result_usec / (double)loops);
  129. printf(" %'14d ops/sec\n",
  130. (int)((double)loops /
  131. ((double)result_usec / (double)1000000)));
  132. break;
  133. case BENCH_FORMAT_SIMPLE:
  134. printf("%lu.%03lu\n",
  135. (unsigned long) diff.tv_sec,
  136. (unsigned long) (diff.tv_usec / 1000));
  137. break;
  138. default:
  139. /* reaching here is something disaster */
  140. fprintf(stderr, "Unknown format:%d\n", bench_format);
  141. exit(1);
  142. break;
  143. }
  144. return 0;
  145. }
  146. int bench_syscall_basic(int argc, const char **argv)
  147. {
  148. return bench_syscall_common(argc, argv, __NR_getppid);
  149. }
  150. int bench_syscall_getpgid(int argc, const char **argv)
  151. {
  152. return bench_syscall_common(argc, argv, __NR_getpgid);
  153. }
  154. int bench_syscall_fork(int argc, const char **argv)
  155. {
  156. return bench_syscall_common(argc, argv, __NR_fork);
  157. }
  158. int bench_syscall_execve(int argc, const char **argv)
  159. {
  160. return bench_syscall_common(argc, argv, __NR_execve);
  161. }