
#include <cstdio>
#include <memory>
#include <thread>
#include <vector>
#include <numeric>
#include <sys/time.h>

const int KDefaultNumIterations = 1000000;
const int KDefaultNumThreads    = 4;

struct dummy
{
  int i;
  float f;
};

void run_mem_alloc_benchmark(int numIterations, float& outRes)
{
  struct timeval start,  end;
  gettimeofday(&start, NULL);

  for (int i = 0; i < numIterations; ++i)
  {
    std::unique_ptr<dummy> temp(new dummy());
  }

  gettimeofday(&end, NULL);

  outRes = (end.tv_sec - start.tv_sec)
         + ((end.tv_usec - start.tv_usec) / 1000000.0f);
}

int main(int argc, char** argv)
{
  if ((argc != 1) && (argc != 3))
  {
    fprintf(stderr, "Usage: %s <num_iterations> <num_threads>\n", argv[0]);
    exit(1);
  }

  int numIterations = KDefaultNumIterations;
  int numThreads = KDefaultNumThreads;

  if (argc == 3)
  {
    numIterations = atoi(argv[1]);
    numThreads = atoi(argv[2]);
  }

  std::vector<float> results(numThreads);
  std::thread threads[numThreads];

  for (int i = 0; i < numThreads; ++i)
  {
    threads[i] = std::thread(run_mem_alloc_benchmark, numIterations, std::ref(results[i]));
  }

  for (int i = 0; i < numThreads; ++i)
  {
    threads[i].join();
  }

  printf("Benchmark results (num iterations = %d, num threads = %d:\n", numIterations, numThreads);
  printf("---------------------------------------------------------\n");
  for (int i = 0; i < numThreads; ++i)
  {
    printf("  [ thread %2d ] Time: %5.3f s\n", i + 1, results[i]);
  }
  printf("---------------------------------------------------------\n");
  printf("Average time: %5.3f s\n", std::accumulate(results.begin(), results.end(), 0.0) / results.size());
}
