他人の空似自作物置場

inc_check.zip/main.cpp


#include <iostream>
#include <vector>
#include <iterator>
#include <array>
#include <numeric>
#include <random>
#include <climits>

#include <boost/format.hpp>
#include <boost/range/irange.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/range/adaptors.hpp>

#include <Windows.h>
#include <mmsystem.h>

#pragma comment(lib, "winmm.lib")

#ifndef _countof
#define _countof(array) (sizeof(array)/sizeof((array)[0]))
#endif

const unsigned int LOOP = 100000000;

unsigned int counter = 0;

class Hoge {
public:
  unsigned int limit;
  unsigned int current;
  std::function<unsigned int()> proc;
  Hoge(const unsigned int limit) : limit(limit), current(0) {
    std::mt19937 mt = std::mt19937(std::random_device()());
    proc = [mt]() mutable {
      return std::uniform_int_distribution<unsigned int>(0U, UINT_MAX)(mt);
    };
  }
  Hoge(const Hoge &other) : limit(other.limit), current(other.current) {
    if ((counter % 1000) == 0) {
      other.proc();
    }
    counter += 1;
  }
  operator bool() const {
    return current != limit;
  }
  Hoge &operator++() {
    current += 1;
    return *this;
  }
  Hoge operator++(int) {
    Hoge result(*this);
    ++*this;
    return result;
  }
};

#ifdef _MSC_VER
#define ASM_NOP() _asm { NOP }
#else
#define ASM_NOP() __asm__("NOP")
#endif

void RangeFor() {
  for (const unsigned int i : boost::irange(0U, LOOP)) {
    ASM_NOP();
  }
}


void Int_PreInc() {
  for (unsigned int i = 0; i < LOOP; ++i) {
    ASM_NOP();
  }
}

void Iterator_PreInc() {
  const auto range = boost::irange(0U, LOOP);
  for (auto it = std::begin(range); it != std::end(range); ++it) {
    ASM_NOP();
  }
}

void Class_PreInc() {
  for (Hoge klass(LOOP); klass; ++klass) {
    ASM_NOP();
  }
}

void Int_PreInc_UseValue() {
  for (unsigned int i = 0; ++i <= LOOP;) {
    ASM_NOP();
  }
}

void Iterator_PreInc_UseValue() {
  const auto range = boost::irange(0U, LOOP);
  for (auto it = std::begin(range); ++it != std::end(range);) {
    ASM_NOP();
  }
}

void Class_PreInc_UseValue() {
  for (Hoge klass(LOOP); ++klass;) {
    ASM_NOP();
  }
}


void Int_PostInc() {
  for (unsigned int i = 0; i < LOOP; i++) {
    ASM_NOP();
  }
}

void Iterator_PostInc() {
  const auto range = boost::irange(0U, LOOP);
  for (auto it = std::begin(range); it != std::end(range); it++) {
    ASM_NOP();
  }
}

void Class_PostInc() {
  for (Hoge klass(LOOP); klass; klass++) {
    ASM_NOP();
  }
}

void Int_PostInc_UseValue() {
  for (unsigned int i = 0; i++ < LOOP;) {
    ASM_NOP();
  }
}

void Iterator_PostInc_UseValue() {
  const auto range = boost::irange(0U, LOOP);
  for (auto it = std::begin(range); it++ != std::end(range);) {
    ASM_NOP();
  }
}

void Class_PostInc_UseValue() {
  for (Hoge klass(LOOP); klass++;) {
    ASM_NOP();
  }
}


template<typename PROC>
void Check(PROC item) {
  static const unsigned int checkCount = 10;
  std::vector<unsigned int> timeList;
  unsigned int total = 0;
  for (const unsigned int i : boost::irange(0U, checkCount)) {
    const DWORD start = ::timeGetTime();
    item.proc();
    const DWORD end = ::timeGetTime();
    const unsigned int result = end - start;
    timeList.push_back(result);
    total += result;
  }
  std::wcout << boost::wformat(L"%s: %dms(%s)\n")
    % item.name
    % (total / checkCount)
    % boost::algorithm::join(timeList | boost::adaptors::transformed([](const unsigned int value) {
      return (boost::wformat(L"%dms") % value).str();
    }), L", ");
}

int main() {
  struct ProcItem {
    std::wstring name;
    void(*proc)();
  };
  std::vector<ProcItem> list = {
    { L"RangeFor", &RangeFor },
    { L"Int_PreInc", &Int_PreInc }, { L"Iterator_PreInc", &Iterator_PreInc }, { L"Class_PreInc", &Class_PreInc },
    { L"Int_PreInc_UseValue", &Int_PreInc_UseValue }, { L"Iterator_PreInc_UseValue", &Iterator_PreInc_UseValue },{ L"Class_PreInc_UseValue", &Class_PreInc_UseValue },
    { L"Int_PostInc", &Int_PostInc }, { L"Iterator_PostInc", &Iterator_PostInc }, { L"Class_PostInc", &Class_PostInc },
    { L"Int_PostInc_UseValue", &Int_PostInc_UseValue }, { L"Iterator_PostInc_UseValue", &Iterator_PostInc_UseValue}, { L"Class_PostInc_UseValue", &Class_PostInc_UseValue },
  };
  for (const ProcItem &item : list) {
    Check(item);
  }
  return 0;
}