/*
rm -f a.out ; gcc ~/a.c && PAGE_ALLOC=1 ./a.out ; ./a.out
 */
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/time.h>

#define COUNT 256*1024
int main (int argc, char **argv)
{
  int i, pages = !!getenv("PAGE_ALLOC");
  unsigned char *base, *ptrs[COUNT] = { 0, };
  struct timeval start, end;
  long long usecs;

  base = calloc(COUNT, 256);
  if (!base)
    return 1;

  for (i = 0; i < COUNT; i++) {
    unsigned char *per_page = malloc (4096);
    unsigned char *packed = base + i * 256;
    ptrs[i] = pages ? per_page : packed;
    *ptrs[i] = 1;
  }

  // Lamers shuffle
  for (i = 0; i < COUNT; i++) {
    int a = rand() % (COUNT/2 - 1);
    int b = COUNT/2 + rand() % (COUNT/2 - 1);
    unsigned char *tmp = ptrs[b];
    ptrs[b] = ptrs[a];
    ptrs[a] = tmp;
  }

  // Time this simple sum ...
  gettimeofday(&start, NULL);
  long sum = 0;
  for (i = 0; i < 1000; i++) {
    int j;
    for (j = 0; j < COUNT; j++) {
//      printf ("ptr %p\n", ptrs[j]);
      if (ptrs[j])
	sum += *ptrs[j];
    }
  }
  gettimeofday(&end, NULL);

  usecs = ((end.tv_sec - start.tv_sec) * 1000000 +
	   (end.tv_usec - start.tv_usec));
  fprintf (stderr, "Sum %ld ", sum);
  fprintf (stderr, "time taken: %ld usecs - type '%s'\n",
	   (long)usecs, pages ? "by page" : "packed");
  return 0;
}
