175 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			175 lines
		
	
	
	
		
			4.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//
 | 
						|
// immer: immutable data structures for C++
 | 
						|
// Copyright (C) 2016, 2017, 2018 Juan Pedro Bolivar Puente
 | 
						|
//
 | 
						|
// This software is distributed under the Boost Software License, Version 1.0.
 | 
						|
// See accompanying file LICENSE or copy at http://boost.org/LICENSE_1_0.txt
 | 
						|
//
 | 
						|
 | 
						|
#pragma once
 | 
						|
 | 
						|
#include "benchmark/config.hpp"
 | 
						|
 | 
						|
#include <immer/set.hpp>
 | 
						|
#include <hash_trie.hpp> // Phil Nash
 | 
						|
#include <boost/container/flat_set.hpp>
 | 
						|
#include <set>
 | 
						|
#include <unordered_set>
 | 
						|
 | 
						|
namespace {
 | 
						|
 | 
						|
template <typename T=unsigned>
 | 
						|
auto make_generator_ranged(std::size_t runs)
 | 
						|
{
 | 
						|
    assert(runs > 0);
 | 
						|
    auto engine = std::default_random_engine{13};
 | 
						|
    auto dist = std::uniform_int_distribution<T>{0, (T)runs-1};
 | 
						|
    auto r = std::vector<T>(runs);
 | 
						|
    std::generate_n(r.begin(), runs, std::bind(dist, engine));
 | 
						|
    return r;
 | 
						|
}
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_access_std()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n  = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n);
 | 
						|
        auto g2 = make_generator_ranged(n);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i)
 | 
						|
                c += v.count(g1[g2[i]]);
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_access_hamt()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n);
 | 
						|
        auto g2 = make_generator_ranged(n);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i) {
 | 
						|
                auto& x = g1[g2[i]];
 | 
						|
                auto leaf = v.find(x).leaf();
 | 
						|
                c += !!(leaf && leaf->find(x));
 | 
						|
            }
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_access()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n);
 | 
						|
        auto g2 = make_generator_ranged(n);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v = v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i)
 | 
						|
                c += v.count(g1[g2[i]]);
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_bad_access_std()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n*2);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i)
 | 
						|
                c += v.count(g1[n+i]);
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_bad_access_hamt()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n*2);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i) {
 | 
						|
                auto& x = g1[n+i];
 | 
						|
                auto leaf = v.find(x).leaf();
 | 
						|
                c += !!(leaf && leaf->find(x));
 | 
						|
            }
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
template <typename Generator, typename Set>
 | 
						|
auto benchmark_bad_access()
 | 
						|
{
 | 
						|
    return [] (nonius::chronometer meter)
 | 
						|
    {
 | 
						|
        auto n = meter.param<N>();
 | 
						|
        auto g1 = Generator{}(n*2);
 | 
						|
 | 
						|
        auto v = Set{};
 | 
						|
        for (auto i = 0u; i < n; ++i)
 | 
						|
            v = v.insert(g1[i]);
 | 
						|
 | 
						|
        measure(meter, [&] {
 | 
						|
            auto c = 0u;
 | 
						|
            for (auto i = 0u; i < n; ++i)
 | 
						|
                c += v.count(g1[n+i]);
 | 
						|
            volatile auto r = c;
 | 
						|
            return r;
 | 
						|
        });
 | 
						|
    };
 | 
						|
}
 | 
						|
 | 
						|
} // namespace
 |