bench_blocksize.c

download raw

#define COPY_ITERS 10

#define ITERS 1000

#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdatomic.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>

#include <sys/eventfd.h>

#define SECOND 1000000000
#define MILLISECOND 1000000
#define MICROSECOND 1000

#define MEG (1024 * 1024)
#define HALFMEG (MEG >> 1)
#define MEG2 (MEG * 2)
#define MEG8 (MEG * 8)

static const uint64_t PHI  = 0x9e3779b97f4a7c15;
static uint64_t rand_state;
static uint64_t rand_u64() {
  rand_state += PHI;
  uint64_t z = rand_state;
  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
  z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
  return z ^ (z >> 31);
}

typedef struct {
  struct timespec start, end;
} bench;

// can fit everything into a float in nanoseconds.
double diff(struct timespec start, struct timespec end)
{
    struct timespec temp;
    if ((end.tv_nsec-start.tv_nsec)<0) {
        temp.tv_sec = end.tv_sec-start.tv_sec-1;
        temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
    } else {
        temp.tv_sec = end.tv_sec-start.tv_sec;
        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
    }
  return (double)((1000000000ULL * (uint64_t)temp.tv_sec) + temp.tv_nsec);
}

void print_stat(double stat) {
  if (stat >= SECOND) {
    printf("%7.3f secs", stat / SECOND);
    return;
  }
  if (stat >= MILLISECOND) {
    printf("%7.3f msec", stat / MILLISECOND);
    return;
  }
  if (stat >= MICROSECOND) {
    printf("%7.3f usec", stat / MICROSECOND);
    return;
  }
  printf("%7.3f nsec", stat);
}

void print_bench(char *name, bench b) {
  double delta = diff(b.start, b.end);
  printf("%-20s ", name);
  print_stat(delta);
  printf(" ( ");
  print_stat(delta / ITERS);
  printf(" per iteration )\n");
}

bench bench_bs512k_thr1_copy(int in, int out, char * buf) {
  bench b;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start);
  for (int block = 0; block < 2048; block++) {
    for (int index = 0; index < HALFMEG; ) {
      ssize_t ret = read(in, &buf[index], HALFMEG - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected read error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
    for (int index = 0; index < HALFMEG; ) {
      ssize_t ret = write(out, &buf[index], HALFMEG - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected write error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
  }
  int ret = fsync(out);
  if (ret == -1) {
    fprintf(stderr, "Unexpected fsync error: %d", errno);
    exit(3);
  }
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end);
  return b;
}

bench bench_bs1m_thr1_copy(int in, int out, char * buf) {
  bench b;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start);
  for (int block = 0; block < 1024; block++) {
    for (int index = 0; index < MEG; ) {
      ssize_t ret = read(in, &buf[index], MEG - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected read error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
    for (int index = 0; index < MEG; ) {
      ssize_t ret = write(out, &buf[index], MEG - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected write error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
  }
  int ret = fsync(out);
  if (ret == -1) {
    fprintf(stderr, "Unexpected fsync error: %d", errno);
    exit(3);
  }
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end);
  return b;
}

bench bench_bs2m_thr1_copy(int in, int out, char * buf) {
  bench b;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start);
  for (int block = 0; block < 512; block++) {
    for (int index = 0; index < MEG2; ) {
      ssize_t ret = read(in, &buf[index], MEG2 - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected read error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
    for (int index = 0; index < MEG; ) {
      ssize_t ret = write(out, &buf[index], MEG2 - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected write error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
  }
  int ret = fsync(out);
  if (ret == -1) {
    fprintf(stderr, "Unexpected fsync error: %d", errno);
    exit(3);
  }
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end);
  return b;
}

bench bench_bs8m_thr1_copy(int in, int out, char * buf) {
  bench b;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.start);
  for (int block = 0; block < 128; block++) {
    for (int index = 0; index < MEG8; ) {
      ssize_t ret = read(in, &buf[index], MEG8 - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected read error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
    for (int index = 0; index < MEG8; ) {
      ssize_t ret = write(out, &buf[index], MEG8 - index);
      if (ret == -1) {
        fprintf(stderr, "Unexpected write error: %d", errno);
        exit(1);
      } else {
        index += ret;
      }
    }
  }
  int ret = fsync(out);
  if (ret == -1) {
    fprintf(stderr, "Unexpected fsync error: %d", errno);
    exit(3);
  }
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &b.end);
  return b;
}

static char buf[8 * MEG];

int main(int argc, char **argv) {
  struct timespec t;
  clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &t);
  int efd = eventfd(0, 0);
  int in = open("random", O_RDWR);
  if (in == -1) {
    fprintf(stderr, "error opening random: %d", errno);
    return 1;
  }
  int out = open(".", O_RDWR | O_TMPFILE);
  if (out == -1) {
    fprintf(stderr, "error opening out: %d", errno);
    return 1;
  }

  memset(buf, 0, sizeof(buf));

  if (argc < 2 || strchr(argv[1], '5')) {
      print_bench("copy bs=512K thr=1", bench_bs512k_thr1_copy(in, out, &buf[0]));
      int ret = lseek(in, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
      ret = lseek(out, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
  }
  if (argc < 2 || strchr(argv[1], '1')) {
      print_bench("copy bs=1M thr=1", bench_bs1m_thr1_copy(in, out, &buf[0]));
      int ret = lseek(in, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
      ret = lseek(out, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
  }
  if (argc < 2 || strchr(argv[1], '2')) {
      print_bench("copy bs=2M thr=1", bench_bs2m_thr1_copy(in, out, &buf[0]));
      int ret = lseek(in, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
      ret = lseek(out, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
  }
  if (argc < 2 || strchr(argv[1], '8')) {
  print_bench("copy bs=8M thr=1", bench_bs8m_thr1_copy(in, out, &buf[0]));
      int ret = lseek(in, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
      ret = lseek(out, 0, SEEK_SET);
      if (ret == -1) {
        fprintf(stderr, "Unexpected lseek error: %d", errno);
        exit(8);
      }
  }
  /* print_bench("copy bs=1M thr=8", bench_bs1m_thr8_copy(in, out, efd, &buf[0])); */

  return 0;
}