
#ifndef PLS_MINI_BENCHMARK_H
#define PLS_MINI_BENCHMARK_H

#include "pls/internal/scheduling/scheduler_memory.h"
#include "pls/internal/scheduling/scheduler.h"

#include <chrono>
#include <iostream>

namespace pls {
namespace internal {
namespace helpers {

// TODO: Clean up (separate into small functions and .cpp file)
template<typename Function>
void run_mini_benchmark(const Function &lambda, size_t max_threads, unsigned long max_runtime_ms = 1000) {
  using namespace std;
  using namespace pls::internal::scheduling;

  malloc_scheduler_memory scheduler_memory{max_threads};
  for (unsigned int num_threads = 1; num_threads <= max_threads; num_threads++) {
    scheduler local_scheduler{&scheduler_memory, num_threads};

    chrono::high_resolution_clock::time_point start_time;
    chrono::high_resolution_clock::time_point end_time;
    unsigned long iterations = 0;
    local_scheduler.perform_work([&] {
      start_time = chrono::high_resolution_clock::now();
      end_time = start_time;
      chrono::high_resolution_clock::time_point planned_end_time = start_time + chrono::milliseconds(max_runtime_ms);

      while (end_time < planned_end_time) {
        lambda();
        end_time = chrono::high_resolution_clock::now();
        iterations++;
      }
    });

    long time = chrono::duration_cast<chrono::microseconds>(end_time - start_time).count();
    double time_per_iteration = (double) time / iterations;

    std::cout << time_per_iteration;
    if (num_threads < max_threads) {
      std::cout << ",";
    }
  }
  std::cout << std::endl;
}

}
}
}

#endif //PLS_MINI_BENCHMARK_H
