<commit_before>#include <iomanip>
#include <iostream>
#include <chrono>
#include "secs/container.h"

namespace chrono = std::chrono;

using std::cout;
using std::endl;
using std::make_unique;
using std::string;
using std::unique_ptr;
using std::vector;

using secs::Container;

struct Velocity {
  float x = 0;
  float y = 0;

  Velocity(float x = 0, float y = 0)
    : x(x), y(y)
  {}
};

static const size_t COUNT = 10000;

template<typename F>
void benchmark(const string& label, F&& body) {
  auto t0 = chrono::high_resolution_clock::now();
  body();
  auto t1 = chrono::high_resolution_clock::now();

  cout << std::left << std::setw(40) << label
       << ": "
       << std::right << std::setw(8)
       << chrono::duration_cast<chrono::nanoseconds>(t1 - t0).count()
       << " ns\n";
}

static std::default_random_engine gen;

float random_number() {
  std::uniform_real_distribution<float> dist(-1, 1);
  return dist(gen);
}

float compute(Velocity& v) {
  return v.x + v.y;
}

////////////////////////////////////////////////////////////////////////////////
void vector_of_values() {
  vector<Velocity> inputs;
  inputs.reserve(COUNT);

  for (size_t i = 0; i < COUNT; ++i) {
    inputs.emplace_back(random_number(), random_number());
  }

  vector<float> outputs;
  outputs.reserve(COUNT);

  benchmark("vector of values", [&]() {
    for (auto& input : inputs) {
      outputs.push_back(compute(input));
    }
  });
}

void vector_of_pointers() {
  vector<unique_ptr<Velocity>> inputs;
  inputs.reserve(COUNT);

  for (size_t i = 0; i < COUNT; ++i) {
    inputs.push_back(make_unique<Velocity>(random_number(), random_number()));
  }

  vector<float> outputs;
  outputs.reserve(COUNT);

  benchmark("vector of pointers", [&]() {
    for (auto& input : inputs) {
      outputs.push_back(compute(*input));
    }
  });
}

void container_with_entity() {
  Container container;

  for (size_t i = 0; i < COUNT; ++i) {
    auto e = container.create();
    e.create_component<Velocity>(random_number(), random_number());
  }

  vector<float> outputs;
  outputs.reserve(COUNT);

  benchmark("container iteration via entity", [&]() {
    for (auto c : container.entities().need<Velocity>()) {
      outputs.push_back(compute(*c.entity().component<Velocity>()));
    }
  });
}

void container_with_cursor() {
  Container container;

  for (size_t i = 0; i < COUNT; ++i) {
    auto e = container.create();
    e.create_component<Velocity>(random_number(), random_number());
  }

  vector<float> outputs;
  outputs.reserve(COUNT);

  benchmark("container iteration via cursor", [&]() {
    for (auto c : container.entities().need<Velocity>()) {
      outputs.push_back(compute(c.get<Velocity>()));
    }
  });
}

int main() {
  vector_of_values();
  vector_of_pointers();
  container_with_entity();
  container_with_cursor();

  return 0;
}<commit_msg>Improves benchmarks<commit_after>#include <iomanip>
#include <iostream>
#include <chrono>
#include "secs/container.h"

// TODO: these benchmarks are too simplisitc be meanigful, improve them!

namespace chrono = std::chrono;

using std::cout;
using std::endl;
using std::make_unique;
using std::string;
using std::unique_ptr;
using std::vector;

using secs::Container;

struct Velocity {
  float x = 0;
  float y = 0;

  Velocity(float x = 0, float y = 0)
    : x(x), y(y)
  {}
};

static const size_t COUNT = 100000;

template<typename F>
void benchmark(const string& label, F&& body) {
  auto t0 = chrono::high_resolution_clock::now();
  body();
  auto t1 = chrono::high_resolution_clock::now();

  cout << std::left << std::setw(40) << label
       << ": "
       << std::right << std::setw(8)
       << chrono::duration_cast<chrono::nanoseconds>(t1 - t0).count()
       << " ns\n";
}

static std::default_random_engine gen;

float random_number() {
  std::uniform_real_distribution<float> dist(-1, 1);
  return dist(gen);
}

float compute(Velocity& v) {
  return v.x + v.y;
}

static float sum = 0;

void use(float value) {
  sum += value;
}

////////////////////////////////////////////////////////////////////////////////
void iterate_vector_of_values() {
  vector<Velocity> inputs;
  inputs.reserve(COUNT);

  for (size_t i = 0; i < COUNT; ++i) {
    inputs.emplace_back(random_number(), random_number());
  }

  float result = 0;

  benchmark("vector of values", [&]() {
    for (auto& input : inputs) {
      result += compute(input);
    }
  });

  use(result);
}

void iterate_vector_of_pointers() {
  vector<unique_ptr<Velocity>> inputs;
  inputs.reserve(COUNT);

  for (size_t i = 0; i < COUNT; ++i) {
    inputs.push_back(make_unique<Velocity>(random_number(), random_number()));
  }

  float result = 0;

  benchmark("vector of pointers", [&]() {
    for (auto& input : inputs) {
      result += compute(*input);
    }
  });

  use(result);
}

void iterate_container_without_load() {
  Container container;

  for (size_t i = 0; i < COUNT; ++i) {
    auto e = container.create();
    e.create_component<Velocity>(random_number(), random_number());
  }

  float result = 0;

  benchmark("container without load", [&]() {
    for (auto e : container.entities()) {
      result += compute(*e.component<Velocity>());
    }
  });

  use(result);
}

void iterate_container_with_load() {
  Container container;

  for (size_t i = 0; i < COUNT; ++i) {
    auto e = container.create();
    e.create_component<Velocity>(random_number(), random_number());
  }

  float result = 0;

  benchmark("container with load", [&]() {
    for (auto e : container.entities().load<Velocity>()) {
      result += compute(*e.component<Velocity>());
    }
  });

  use(result);
}

void compare_component_ptr_and_raw_ptr() {
  Container container;

  for (size_t i = 0; i < COUNT; ++i) {
    auto e = container.create();
    e.create_component<Velocity>(random_number(), random_number());
  }

  std::vector<secs::ComponentPtr<Velocity>> component_ptrs;
  component_ptrs.reserve(COUNT);

  std::vector<Velocity*> raw_ptrs;
  raw_ptrs.reserve(COUNT);

  for (auto e : container.entities().need<Velocity>()) {
    component_ptrs.push_back(e.component<Velocity>());
    raw_ptrs.push_back(e.component<Velocity>().get());
  }

  float result = 0;

  benchmark("ComponentPtr<T> access", [&]() {
    for (auto p : component_ptrs) {
      result += compute(*p);
    }
  });

  benchmark("T* access", [&]() {
    for (auto p : raw_ptrs) {
      result += compute(*p);
    }
  });

  use(result);
}

int main() {
  iterate_vector_of_values();
  iterate_vector_of_pointers();
  iterate_container_without_load();
  iterate_container_with_load();

  compare_component_ptr_and_raw_ptr();

  return 0;
}
{'fraction_non_alphanumeric': 0.18733031674208145, 'fraction_numerical': 0.008144796380090498, 'mean_word_length': 3.5231923601637107, 'pattern_counts': {'":': 2, '<': 87, '<?xml version=': 0, '>': 46, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3993920', 'n_tokens_mistral': 2372, 'n_tokens_neox': 2259, 'n_words': 475}