memsize.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*
  2. * memsize.c - figure out how much memory we have to use.
  3. *
  4. * Usage: memsize [max_wanted_in_MB]
  5. *
  6. * Copyright (c) 1995 Larry McVoy. Distributed under the FSF GPL with
  7. * additional restriction that results may published only if
  8. * (1) the benchmark is unmodified, and
  9. * (2) the version in the sccsid below is included in the report.
  10. */
  11. char *id = "$Id$\n";
  12. #include "bench.h"
  13. #define CHK(x) if ((x) == -1) { perror("x"); exit(1); }
  14. #ifndef TOO_LONG
  15. #define TOO_LONG 10 /* usecs */
  16. #endif
  17. int alarm_triggered = 0;
  18. void timeit(char *where, size_t size);
  19. static void touchRange(char *p, size_t range, ssize_t stride);
  20. int test_malloc(size_t size);
  21. void set_alarm(uint64 usecs);
  22. void clear_alarm();
  23. int
  24. main(int ac, char **av)
  25. {
  26. char *where;
  27. char *tmp;
  28. size_t size = 0;
  29. size_t max = 0;
  30. size_t delta;
  31. if (ac == 2) {
  32. max = size = bytes(av[1]) * 1024 * 1024;
  33. }
  34. if (max < 1024 * 1024) {
  35. max = size = 1024 * 1024 * 1024;
  36. }
  37. /*
  38. * Binary search down and then binary search up
  39. */
  40. for (where = 0; !test_malloc(size); size >>= 1) {
  41. max = size;
  42. }
  43. /* delta = size / (2 * 1024 * 1024) */
  44. for (delta = (size >> 21); delta > 0; delta >>= 1) {
  45. uint64 sz = (uint64)size + (uint64)delta * 1024 * 1024;
  46. if (max < sz) continue;
  47. if (test_malloc(sz)) size = sz;
  48. }
  49. if (where = malloc(size)) {
  50. timeit(where, size);
  51. free(where);
  52. }
  53. exit (0);
  54. }
  55. void
  56. timeit(char *where, size_t size)
  57. {
  58. int sum = 0;
  59. char *end = where + size;
  60. size_t n;
  61. size_t s;
  62. size_t range;
  63. size_t incr = 1024 * 1024;
  64. ssize_t stride;
  65. size_t pagesize = getpagesize();
  66. if (size < 1024*1024 - 16*1024) {
  67. fprintf(stderr, "Bad size\n");
  68. return;
  69. }
  70. range = 1024 * 1024;
  71. incr = 1024 * 1024;
  72. touchRange(where, range, pagesize);
  73. for (range += incr; range <= size; range += incr) {
  74. n = range / pagesize;
  75. set_alarm(n * TOO_LONG);
  76. touchRange(where + range - incr, incr, pagesize);
  77. clear_alarm();
  78. set_alarm(n * TOO_LONG);
  79. start(0);
  80. touchRange(where, range, pagesize);
  81. sum = stop(0, 0);
  82. clear_alarm();
  83. if ((sum / n) > TOO_LONG || alarm_triggered) {
  84. size = range - incr;
  85. break;
  86. }
  87. for (s = 8 * 1024 * 1024; s <= range; s *= 2)
  88. ;
  89. incr = s / 8;
  90. if (range < size && size < range + incr) {
  91. incr = size - range;
  92. }
  93. fprintf(stderr, "%dMB OK\r", range/(1024*1024));
  94. }
  95. fprintf(stderr, "\n");
  96. printf("%d\n", (size>>20));
  97. }
  98. static void
  99. touchRange(char *p, size_t range, ssize_t stride)
  100. {
  101. register char *tmp = p + (stride > 0 ? 0 : range - 1);
  102. register size_t delta = (stride > 0 ? stride : -stride);
  103. while (range > delta - 1 && !alarm_triggered) {
  104. *tmp = 0;
  105. tmp += stride;
  106. range -= delta;
  107. }
  108. }
  109. int
  110. test_malloc(size_t size)
  111. {
  112. int fid[2];
  113. int result;
  114. int status;
  115. void* p;
  116. if (pipe(fid) < 0) {
  117. void* p = malloc(size);
  118. if (!p) return 0;
  119. free(p);
  120. return 1;
  121. }
  122. if (fork() == 0) {
  123. close(fid[0]);
  124. p = malloc(size);
  125. result = (p ? 1 : 0);
  126. write(fid[1], &result, sizeof(int));
  127. close(fid[1]);
  128. if (p) free(p);
  129. exit(0);
  130. }
  131. close(fid[1]);
  132. if (read(fid[0], &result, sizeof(int)) != sizeof(int))
  133. result = 0;
  134. close(fid[0]);
  135. wait(&status);
  136. return result;
  137. }
  138. void
  139. gotalarm()
  140. {
  141. alarm_triggered = 1;
  142. }
  143. void
  144. set_alarm(uint64 usecs)
  145. {
  146. struct itimerval value;
  147. struct sigaction sa;
  148. alarm_triggered = 0;
  149. sa.sa_handler = gotalarm;
  150. sigemptyset(&sa.sa_mask);
  151. sa.sa_flags = 0;
  152. sigaction(SIGALRM, &sa, 0);
  153. value.it_interval.tv_sec = 0;
  154. value.it_interval.tv_usec = 0;
  155. value.it_value.tv_sec = usecs / 1000000;
  156. value.it_value.tv_usec = usecs % 1000000;
  157. setitimer(ITIMER_REAL, &value, NULL);
  158. }
  159. void
  160. clear_alarm()
  161. {
  162. struct itimerval value;
  163. value.it_interval.tv_sec = 0;
  164. value.it_interval.tv_usec = 0;
  165. value.it_value.tv_sec = 0;
  166. value.it_value.tv_usec = 0;
  167. setitimer(ITIMER_REAL, &value, NULL);
  168. }