Skip to content

Instantly share code, notes, and snippets.

@onihusube
Last active April 17, 2020 13:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save onihusube/b772839e3da0712284cabf249d7a2d13 to your computer and use it in GitHub Desktop.
Save onihusube/b772839e3da0712284cabf249d7a2d13 to your computer and use it in GitHub Desktop.
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <charconv>
#include <vector>
#include <random>
#include <chrono>
#include <type_traits>
#include <cassert>
#include <thread>
#include <numeric>
#include <string>
#include <string_view>
#include <sstream>
template<typename NumericType>
auto make_data(std::uint64_t N) -> std::pair<std::vector<char>, std::vector<std::string_view>> {
auto rng = []() {
if constexpr (std::is_integral_v<NumericType>) {
return std::uniform_int_distribution<NumericType>{};
}
else if constexpr (std::is_floating_point_v<NumericType>) {
return std::uniform_real_distribution<NumericType>{};
}
else {
static_assert([] { return false; }, "You have to specify a number type, right?");
}
}();
std::mt19937_64 urbg{ std::random_device{}() };
std::vector<char> buffer(N * 21ull, '\0');
auto* pos = buffer.data();
std::vector<std::string_view> vec;
vec.reserve(N);
for (auto i = 0u; i < N; ++i) {
const auto num = rng(urbg);
const auto [end, ec] = std::to_chars(pos, pos + 21, num);
if (ec != std::errc{}) {
--i;
continue;
}
const std::size_t len = end - pos;
vec.emplace_back(pos, len);
pos += (len + 1);
}
return { std::move(buffer), std::move(vec) };
}
template<typename Container>
void report(Container&& container) {
const auto first = std::begin(container);
const auto last = std::end(container);
const auto N = std::size(container);
using value_type = typename std::iterator_traits<std::remove_const_t<decltype(first)>>::value_type;
std::sort(first, last);
const auto max = *(last - 1);
const auto min = *first;
std::cout << "min : " << min.count() << " [ms]" << std::endl;
std::cout << "max : " << max.count() << " [ms]" << std::endl;
const auto medpos = first + (N / 2);
std::cout << "median : " << (*medpos).count() << " [ms]" << std::endl;
const auto sum = std::accumulate(first, last, value_type{});
const auto ave = sum.count() / double(N);
std::cout << "average : " << ave << " [ms]" << std::endl;
const auto var = std::inner_product(first, last, first, 0ll, std::plus<>{},
[](auto& lhs, auto& rhs) {return lhs.count() * rhs.count(); }) / N - (ave * ave);
std::cout << "stddev : " << std::sqrt(var) << "\n" << std::endl;
}
template<typename NumericType, typename F>
void profiling(const char* target, F&& func) {
using namespace std::chrono_literals;
constexpr int trialN = 10;
constexpr int sampleN = 1'000'000;
std::chrono::milliseconds results[trialN]{};
for (int i = 0; i < trialN; ++i) {
//データの準備
auto [buf, input] = make_data<NumericType>(sampleN);
//計測開始
auto start = std::chrono::steady_clock::now();
for (auto sv : input) {
func(sv);
}
//計測終了
auto end = std::chrono::steady_clock::now();
results[i] = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
std::this_thread::sleep_for(200ms);
}
std::cout << target << std::endl;
report(results);
}
int main()
{
std::int64_t v;
profiling<std::int64_t>("to_chars() int64", [&v](auto sv) {
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.length(), v);
if (ec != std::errc{}) throw new std::exception{};
});
profiling<std::int64_t>("stoll() int64", [&v](auto sv) {
v = std::stoll(std::string{ sv });
});
std::stringstream stm{};
profiling<std::int64_t>("stringstream int64", [&stm, &v](auto sv) {
stm << sv;
stm >> v;
if (stm.fail()) stm.clear(); //エラー起きる原因分からん・・・
});
profiling<std::int64_t>("sscanf() int64", [&v](auto sv) {
auto r = sscanf(sv.data(), "%lld", &v);
if (r < 0) throw new std::exception{};
});
char* err{};
profiling<std::int64_t>("strtoll() int64", [&v, &err](auto sv) {
v = strtoll(sv.data(), &err, 10);
if (sv.data() == err) throw new std::exception{};
});
double d;
profiling<double>("from_chars() double", [&d](auto sv) {
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.length(), d);
if (ec != std::errc{}) throw new std::exception{};
});
profiling<double>("stod() double", [&d](auto sv) {
d = std::stod(std::string{ sv });
});
profiling<double>("stringstream double", [&stm, &d](auto sv) {
stm << sv;
stm >> d;
if (stm.fail()) stm.clear(); //エラー起きる原因分からん・・・
});
profiling<double>("sscanf() double", [&d](auto sv) {
auto r = sscanf(sv.data(), "%lg", &d);
if (r < 0) throw new std::exception{};
});
profiling<double>("strtod() double", [&d, &err](auto sv) {
d = strtod(sv.data(), &err);
if (sv.data() == err) throw new std::exception{};
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment