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;
}