// Microbenchmarks for ThreadPoolDevice scheduling overhead.
// SPDX-FileCopyrightText: The Eigen Authors
// SPDX-License-Identifier: MPL-2.0

#define EIGEN_USE_THREADS

#include <atomic>
#include <map>
#include <memory>
#include <mutex>

#include <benchmark/benchmark.h>
#include <Eigen/ThreadPool>
#include <contrib/Eigen/Tensor>

using Eigen::Index;
using Eigen::TensorOpCost;
using Eigen::ThreadPool;
using Eigen::ThreadPoolDevice;

// Returns a per-thread-count singleton device, lazily created on first use.
// Pools are reused across benchmark iterations so thread-creation cost does
// not enter the measurement, and varying thread counts across benchmarks is
// supported without later calls silently colliding with the first one.
static ThreadPoolDevice& device(int threads) {
  static std::mutex mu;
  static std::map<int, std::unique_ptr<ThreadPool>> pools;
  static std::map<int, std::unique_ptr<ThreadPoolDevice>> devs;
  std::lock_guard<std::mutex> lock(mu);
  auto it = devs.find(threads);
  if (it != devs.end()) return *it->second;
  auto pool = std::unique_ptr<ThreadPool>(new ThreadPool(threads));
  auto* dev = new ThreadPoolDevice(pool.get(), threads);
  pools.emplace(threads, std::move(pool));
  devs.emplace(threads, std::unique_ptr<ThreadPoolDevice>(dev));
  return *dev;
}

// ---- enqueue overhead: empty lambda, wait via shared counter -------------
static void BM_EnqueueEmpty(benchmark::State& state) {
  const int threads = state.range(0);
  auto& dev = device(threads);
  const int batch = 1024;
  for (auto _ : state) {
    std::atomic<int> remaining{batch};
    for (int i = 0; i < batch; ++i) {
      dev.enqueue([&remaining] { remaining.fetch_sub(1, std::memory_order_release); });
    }
    while (remaining.load(std::memory_order_acquire) != 0) {
    }
  }
  state.SetItemsProcessed(state.iterations() * batch);
  state.counters["threads"] = threads;
}
BENCHMARK(BM_EnqueueEmpty)->Arg(8)->UseRealTime();

// ---- parallelFor with tiny per-element cost: dispatch overhead dominates --
static void BM_ParallelForTiny(benchmark::State& state) {
  const Index n = state.range(0);
  const int threads = state.range(1);
  auto& dev = device(threads);
  // Cost just large enough that the cost model decides to parallelize.
  const TensorOpCost cost(/*bytes_loaded=*/4, /*bytes_stored=*/4, /*compute_cycles=*/4);
  std::atomic<Index> sink{0};
  for (auto _ : state) {
    dev.parallelFor(n, cost,
                    [&sink](Index first, Index last) { sink.fetch_add(last - first, std::memory_order_relaxed); });
  }
  benchmark::DoNotOptimize(sink.load());
  state.SetItemsProcessed(state.iterations() * n);
  state.counters["threads"] = threads;
}
BENCHMARK(BM_ParallelForTiny)->Args({256, 8})->Args({4096, 8})->Args({65536, 8})->Args({1048576, 8})->UseRealTime();

// ---- parallelFor with realistic per-element compute work ------------------
static void BM_ParallelForCompute(benchmark::State& state) {
  const Index n = state.range(0);
  const int threads = state.range(1);
  auto& dev = device(threads);
  const TensorOpCost cost(/*bytes_loaded=*/8, /*bytes_stored=*/8, /*compute_cycles=*/32);
  std::vector<double> data(n, 1.0);
  for (auto _ : state) {
    dev.parallelFor(n, cost, [&data](Index first, Index last) {
      for (Index i = first; i < last; ++i) {
        data[i] = data[i] * 1.0000001 + 1e-12;
      }
    });
    benchmark::DoNotOptimize(data.data());
  }
  state.SetItemsProcessed(state.iterations() * n);
  state.counters["threads"] = threads;
}
BENCHMARK(BM_ParallelForCompute)->Args({4096, 8})->Args({65536, 8})->Args({1048576, 8})->UseRealTime();

// ---- parallelForAsync: measures async dispatch + heap context overhead ----
static void BM_ParallelForAsync(benchmark::State& state) {
  const Index n = state.range(0);
  const int threads = state.range(1);
  auto& dev = device(threads);
  const TensorOpCost cost(8, 8, 4);
  for (auto _ : state) {
    std::atomic<int> done_flag{0};
    dev.parallelForAsync(
        n, cost, [](Index, Index) {}, [&done_flag] { done_flag.store(1, std::memory_order_release); });
    while (done_flag.load(std::memory_order_acquire) == 0) {
    }
  }
  state.SetItemsProcessed(state.iterations() * n);
  state.counters["threads"] = threads;
}
BENCHMARK(BM_ParallelForAsync)->Args({4096, 8})->Args({65536, 8})->Args({1048576, 8})->UseRealTime();

// ---- ThreadPoolDevice::memcpy at various sizes ----------------------------
static void BM_DeviceMemcpy(benchmark::State& state) {
  const size_t bytes = state.range(0);
  const int threads = state.range(1);
  auto& dev = device(threads);
  std::vector<char> src(bytes), dst(bytes);
  for (auto _ : state) {
    dev.memcpy(dst.data(), src.data(), bytes);
    benchmark::DoNotOptimize(dst.data());
  }
  state.SetBytesProcessed(state.iterations() * bytes);
  state.counters["threads"] = threads;
}
BENCHMARK(BM_DeviceMemcpy)
    ->Args({16 << 10, 8})
    ->Args({256 << 10, 8})
    ->Args({4 << 20, 8})
    ->Args({64 << 20, 8})
    ->UseRealTime();

BENCHMARK_MAIN();
