123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- /*
- * memsize.c - figure out how much memory we have to use.
- *
- * Usage: memsize [max_wanted_in_MB]
- *
- * Copyright (c) 1995 Larry McVoy. Distributed under the FSF GPL with
- * additional restriction that results may published only if
- * (1) the benchmark is unmodified, and
- * (2) the version in the sccsid below is included in the report.
- */
- char *id = "$Id$\n";
- #include "bench.h"
- #define CHK(x) if ((x) == -1) { perror("x"); exit(1); }
- #ifndef TOO_LONG
- #define TOO_LONG 10 /* usecs */
- #endif
- int alarm_triggered = 0;
- void timeit(char *where, size_t size);
- static void touchRange(char *p, size_t range, ssize_t stride);
- int test_malloc(size_t size);
- void set_alarm(uint64 usecs);
- void clear_alarm();
- int
- main(int ac, char **av)
- {
- char *where;
- char *tmp;
- size_t size = 0;
- size_t max = 0;
- size_t delta;
- if (ac == 2) {
- max = size = bytes(av[1]) * 1024 * 1024;
- }
- if (max < 1024 * 1024) {
- max = size = 1024 * 1024 * 1024;
- }
- /*
- * Binary search down and then binary search up
- */
- for (where = 0; !test_malloc(size); size >>= 1) {
- max = size;
- }
- /* delta = size / (2 * 1024 * 1024) */
- for (delta = (size >> 21); delta > 0; delta >>= 1) {
- uint64 sz = (uint64)size + (uint64)delta * 1024 * 1024;
- if (max < sz) continue;
- if (test_malloc(sz)) size = sz;
- }
- if (where = malloc(size)) {
- timeit(where, size);
- free(where);
- }
- exit (0);
- }
- void
- timeit(char *where, size_t size)
- {
- int sum = 0;
- char *end = where + size;
- size_t n;
- size_t s;
- size_t range;
- size_t incr = 1024 * 1024;
- ssize_t stride;
- size_t pagesize = getpagesize();
- if (size < 1024*1024 - 16*1024) {
- fprintf(stderr, "Bad size\n");
- return;
- }
- range = 1024 * 1024;
- incr = 1024 * 1024;
- touchRange(where, range, pagesize);
- for (range += incr; range <= size; range += incr) {
- n = range / pagesize;
- set_alarm(n * TOO_LONG);
- touchRange(where + range - incr, incr, pagesize);
- clear_alarm();
- set_alarm(n * TOO_LONG);
- start(0);
- touchRange(where, range, pagesize);
- sum = stop(0, 0);
- clear_alarm();
- if ((sum / n) > TOO_LONG || alarm_triggered) {
- size = range - incr;
- break;
- }
- for (s = 8 * 1024 * 1024; s <= range; s *= 2)
- ;
- incr = s / 8;
- if (range < size && size < range + incr) {
- incr = size - range;
- }
- fprintf(stderr, "%dMB OK\r", range/(1024*1024));
- }
- fprintf(stderr, "\n");
- printf("%d\n", (size>>20));
- }
- static void
- touchRange(char *p, size_t range, ssize_t stride)
- {
- register char *tmp = p + (stride > 0 ? 0 : range - 1);
- register size_t delta = (stride > 0 ? stride : -stride);
- while (range > delta - 1 && !alarm_triggered) {
- *tmp = 0;
- tmp += stride;
- range -= delta;
- }
- }
- int
- test_malloc(size_t size)
- {
- int fid[2];
- int result;
- int status;
- void* p;
- if (pipe(fid) < 0) {
- void* p = malloc(size);
- if (!p) return 0;
- free(p);
- return 1;
- }
- if (fork() == 0) {
- close(fid[0]);
- p = malloc(size);
- result = (p ? 1 : 0);
- write(fid[1], &result, sizeof(int));
- close(fid[1]);
- if (p) free(p);
- exit(0);
- }
- close(fid[1]);
- if (read(fid[0], &result, sizeof(int)) != sizeof(int))
- result = 0;
- close(fid[0]);
- wait(&status);
- return result;
- }
- void
- gotalarm()
- {
- alarm_triggered = 1;
- }
- void
- set_alarm(uint64 usecs)
- {
- struct itimerval value;
- struct sigaction sa;
- alarm_triggered = 0;
- sa.sa_handler = gotalarm;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = 0;
- sigaction(SIGALRM, &sa, 0);
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- value.it_value.tv_sec = usecs / 1000000;
- value.it_value.tv_usec = usecs % 1000000;
- setitimer(ITIMER_REAL, &value, NULL);
- }
- void
- clear_alarm()
- {
- struct itimerval value;
- value.it_interval.tv_sec = 0;
- value.it_interval.tv_usec = 0;
- value.it_value.tv_sec = 0;
- value.it_value.tv_usec = 0;
- setitimer(ITIMER_REAL, &value, NULL);
- }
|