Guest User

Untitled

a guest
Jan 16th, 2019
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.06 KB | None | 0 0
  1. void func1(int x)
  2. {
  3. /* some processing */
  4.  
  5. func2(y);
  6.  
  7. /* some processing */
  8.  
  9. }
  10.  
  11. void func1(int x)
  12. {
  13. /* some processing */
  14.  
  15. /* some processing */
  16.  
  17. }
  18.  
  19. if (g_flg == 1) {func2(y);}
  20.  
  21. func2(y);
  22.  
  23. struct Something;
  24. typedef struct Something Something;
  25.  
  26. int myFunction(Something * me, int i)
  27. {
  28. // do a bunch of stuff
  29. return 42; // obviously the answer
  30. }
  31.  
  32. int myFunctionDoNothing(Something * dummy1, int dummy2)
  33. {
  34. return 0;
  35. }
  36.  
  37. int (*function)(Something *, int) = myFunctionDoNothing;
  38.  
  39. // snip to actual use of function
  40.  
  41. int i;
  42.  
  43. function = myFunctionDoNothing;
  44. for (i = 0; i < 100000; ++i) function(NULL, 5 * i); // does nothing
  45.  
  46. function = myFunction;
  47. for (i = 0; i < 100000; ++i) function(NULL, 5 * i); // does something
  48.  
  49. /* test.c */
  50.  
  51. volatile long test_calls = 0L;
  52. volatile long test_sum = 0L;
  53.  
  54. void test(long counter)
  55. {
  56. test_calls++;
  57. test_sum += counter;
  58. }
  59.  
  60. /* work.c */
  61.  
  62. void test(long counter);
  63.  
  64. /* Work function, to be measured */
  65. void test_work(long counter, int flag)
  66. {
  67. if (flag)
  68. test(counter);
  69. }
  70.  
  71. /* Dummy function, to measure call overhead */
  72. void test_none(long counter __attribute__((unused)), int flag __attribute__((unused)) )
  73. {
  74. return;
  75. }
  76.  
  77. #define _POSIX_C_SOURCE 200809L
  78. #include <unistd.h>
  79. #include <stdlib.h>
  80. #include <time.h>
  81. #include <stdint.h>
  82. #include <string.h>
  83. #include <stdio.h>
  84.  
  85. /* From test.c */
  86. extern volatile long test_calls;
  87. extern volatile long test_sum;
  88.  
  89. /* Dummy function, to measure call overhead */
  90. void test_none(long counter, int flag);
  91.  
  92. /* Work function, to be measured */
  93. void test_work(long counter, int flag);
  94.  
  95. /* Timing harness -- GCC x86; modify for other architectures */
  96. struct timing {
  97. struct timespec wall_start;
  98. struct timespec wall_stop;
  99. uint64_t cpu_start;
  100. uint64_t cpu_stop;
  101. };
  102.  
  103. static inline void start_timing(struct timing *const mark)
  104. {
  105. clock_gettime(CLOCK_REALTIME, &(mark->wall_start));
  106. mark->cpu_start = __builtin_ia32_rdtsc();
  107. }
  108.  
  109. static inline void stop_timing(struct timing *const mark)
  110. {
  111. mark->cpu_stop = __builtin_ia32_rdtsc();
  112. clock_gettime(CLOCK_REALTIME, &(mark->wall_stop));
  113. }
  114.  
  115. static inline double cpu_timing(const struct timing *const mark)
  116. {
  117. return (double)(mark->cpu_stop - mark->cpu_start); /* Cycles */
  118. }
  119.  
  120. static inline double wall_timing(const struct timing *const mark)
  121. {
  122. return (double)(mark->wall_stop.tv_sec - mark->wall_start.tv_sec)
  123. + (double)(mark->wall_stop.tv_nsec - mark->wall_start.tv_nsec) / 1000000000.0;
  124. }
  125.  
  126. static int cmpdouble(const void *aptr, const void *bptr)
  127. {
  128. const double a = *(const double *)aptr;
  129. const double b = *(const double *)bptr;
  130.  
  131. if (a < b)
  132. return -1;
  133. else
  134. if (a > b)
  135. return +1;
  136. else
  137. return 0;
  138. }
  139.  
  140. void report(double *const wall, double *const cpu, const size_t count)
  141. {
  142. printf("tInitial call: %.0f cpu cycles, %.9f seconds real timen", cpu[0], wall[0]);
  143.  
  144. qsort(wall, count, sizeof (double), cmpdouble);
  145. qsort(cpu, count, sizeof (double), cmpdouble);
  146.  
  147. printf("tMinimum: %.0f cpu cycles, %.9f seconds real timen", cpu[0], wall[0]);
  148. printf("t5%% less than %.0f cpu cycles, %.9f seconds real timen", cpu[count/20], wall[count/20]);
  149. printf("t25%% less than %.0f cpu cycles, %.9f seconds real timen", cpu[count/4], wall[count/4]);
  150. printf("tMedian: %.0f cpu cycles, %.9f seconds real timen", cpu[count/2], wall[count/2]);
  151. printf("t75%% less than %.0f cpu cycles, %.9f seconds real timen", cpu[count-count/4-1], wall[count-count/4-1]);
  152. printf("t95%% less than %.0f cpu cycles, %.9f seconds real timen", cpu[count-count/20-1], wall[count-count/20-1]);
  153. printf("tMaximum: %.0f cpu cycles, %.9f seconds real timen", cpu[count-1], wall[count-1]);
  154. }
  155.  
  156. int main(int argc, char *argv[])
  157. {
  158. struct timing measurement;
  159. double *wall_seconds = NULL;
  160. double *cpu_cycles = NULL;
  161. unsigned long count = 0UL;
  162. unsigned long i;
  163. int flag;
  164. char dummy;
  165.  
  166. if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
  167. fprintf(stderr, "n");
  168. fprintf(stderr, "Usage: %s COUNT FLAGn", argv[0]);
  169. fprintf(stderr, "n");
  170. return 1;
  171. }
  172.  
  173. if (sscanf(argv[1], " %lu %c", &count, &dummy) != 1) {
  174. fprintf(stderr, "%s: Invalid COUNT.n", argv[1]);
  175. return 1;
  176. }
  177. if (count < 1UL) {
  178. fprintf(stderr, "%s: COUNT is too small.n", argv[1]);
  179. return 1;
  180. }
  181. if (!(unsigned long)(count + 1UL)) {
  182. fprintf(stderr, "%s: COUNT is too large.n", argv[1]);
  183. return 1;
  184. }
  185.  
  186. if (sscanf(argv[2], " %d %c", &flag, &dummy) != 1) {
  187. fprintf(stderr, "%s: Invalid FLAG.n", argv[2]);
  188. return 1;
  189. }
  190.  
  191. wall_seconds = malloc(sizeof (double) * (size_t)count);
  192. cpu_cycles = malloc(sizeof (double) * (size_t)count);
  193. if (!wall_seconds || !cpu_cycles) {
  194. free(cpu_cycles);
  195. free(wall_seconds);
  196. fprintf(stderr, "Cannot allocate enough memory. Try smaller COUNT.n");
  197. return 1;
  198. }
  199.  
  200. printf("Call and measurement overhead:n");
  201. fflush(stdout);
  202. for (i = 0UL; i < count; i++) {
  203.  
  204. start_timing(&measurement);
  205. test_none(i, flag);
  206. stop_timing(&measurement);
  207.  
  208. wall_seconds[i] = wall_timing(&measurement);
  209. cpu_cycles[i] = cpu_timing(&measurement);
  210. }
  211. report(wall_seconds, cpu_cycles, (size_t)count);
  212.  
  213. printf("n");
  214. printf("Measuring FLAG==0 calls: ");
  215. fflush(stdout);
  216. test_calls = 0L;
  217. test_sum = 0L;
  218. for (i = 0UL; i < count; i++) {
  219.  
  220. start_timing(&measurement);
  221. test_work(i, 0);
  222. stop_timing(&measurement);
  223.  
  224. wall_seconds[i] = wall_timing(&measurement);
  225. cpu_cycles[i] = cpu_timing(&measurement);
  226. }
  227. printf("%ld calls, sum %ld.n", test_calls, test_sum);
  228. report(wall_seconds, cpu_cycles, (size_t)count);
  229.  
  230. printf("n");
  231. printf("Measuring FLAG==%d calls:", flag);
  232. fflush(stdout);
  233. test_calls = 0L;
  234. test_sum = 0L;
  235. for (i = 0UL; i < count; i++) {
  236.  
  237. start_timing(&measurement);
  238. test_work(i, flag);
  239. stop_timing(&measurement);
  240.  
  241. wall_seconds[i] = wall_timing(&measurement);
  242. cpu_cycles[i] = cpu_timing(&measurement);
  243. }
  244. printf("%ld calls, sum %ld.n", test_calls, test_sum);
  245. report(wall_seconds, cpu_cycles, (size_t)count);
  246.  
  247.  
  248. printf("n");
  249. printf("Measuring alternating FLAG calls: ");
  250. fflush(stdout);
  251. test_calls = 0L;
  252. test_sum = 0L;
  253. for (i = 0UL; i < count; i++) {
  254.  
  255. start_timing(&measurement);
  256. test_work(i, i & 1);
  257. stop_timing(&measurement);
  258.  
  259. wall_seconds[i] = wall_timing(&measurement);
  260. cpu_cycles[i] = cpu_timing(&measurement);
  261. }
  262. printf("%ld calls, sum %ld.n", test_calls, test_sum);
  263. report(wall_seconds, cpu_cycles, (size_t)count);
  264.  
  265. printf("n");
  266. free(cpu_cycles);
  267. free(wall_seconds);
  268. return 0;
  269. }
  270.  
  271. rm -f *.o
  272. gcc -W -Wall -O3 -fomit-frame-pointer -c harness.c
  273. gcc -W -Wall -O3 -fomit-frame-pointer -c work.c
  274. gcc -W -Wall -O3 -fomit-frame-pointer -c test.c
  275. gcc harness.o work.o test.o -lrt -o call-test
  276.  
  277. ./call-test 1000000 1
  278.  
  279. if (flag)
  280. debug_function_call();
Add Comment
Please, Sign In to add comment