mirror of https://github.com/procxx/kepka.git
				
				
				
			
		
			
				
	
	
		
			185 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			185 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			C++
		
	
	
	
| #include <algorithm>
 | |
| #include <cstdlib>
 | |
| #include <iostream>
 | |
| #include <memory>
 | |
| #include <string>
 | |
| #include <thread>
 | |
| #include <utility>
 | |
| #include <vector>
 | |
| 
 | |
| #include "auto_cpu_timer.hpp"
 | |
| 
 | |
| #include <boost/variant.hpp>
 | |
| #include <mapbox/variant.hpp>
 | |
| 
 | |
| #define TEXT_SHORT "Test"
 | |
| #define TEXT_LONG "Testing various variant implementations with a longish string ........................................."
 | |
| #define NUM_SAMPLES 3
 | |
| //#define BOOST_VARIANT_MINIMIZE_SIZE
 | |
| 
 | |
| using namespace mapbox;
 | |
| 
 | |
| namespace test {
 | |
| 
 | |
| template <typename V>
 | |
| struct Holder
 | |
| {
 | |
|     typedef V value_type;
 | |
|     std::vector<value_type> data;
 | |
| 
 | |
|     template <typename T>
 | |
|     void append_move(T&& obj)
 | |
|     {
 | |
|         data.emplace_back(std::forward<T>(obj));
 | |
|     }
 | |
| 
 | |
|     template <typename T>
 | |
|     void append(T const& obj)
 | |
|     {
 | |
|         data.push_back(obj);
 | |
|     }
 | |
| };
 | |
| 
 | |
| } // namespace test
 | |
| 
 | |
| struct print
 | |
| {
 | |
|     template <typename T>
 | |
|     void operator()(T const& val) const
 | |
|     {
 | |
|         std::cerr << val << ":" << typeid(T).name() << std::endl;
 | |
|     }
 | |
| };
 | |
| 
 | |
| template <typename V>
 | |
| struct dummy : boost::static_visitor<>
 | |
| {
 | |
|     dummy(V& v)
 | |
|         : v_(v) {}
 | |
| 
 | |
|     template <typename T>
 | |
|     void operator()(T&& val) const
 | |
|     {
 | |
|         v_ = std::move(val);
 | |
|     }
 | |
|     V& v_;
 | |
| };
 | |
| 
 | |
| template <typename V>
 | |
| struct dummy2
 | |
| {
 | |
|     dummy2(V& v)
 | |
|         : v_(v) {}
 | |
| 
 | |
|     template <typename T>
 | |
|     void operator()(T&& val) const
 | |
|     {
 | |
|         v_ = std::move(val);
 | |
|     }
 | |
|     V& v_;
 | |
| };
 | |
| 
 | |
| void run_boost_test(std::size_t runs)
 | |
| {
 | |
|     test::Holder<boost::variant<int, double, std::string>> h;
 | |
|     h.data.reserve(runs);
 | |
|     for (std::size_t i = 0; i < runs; ++i)
 | |
|     {
 | |
|         h.append_move(std::string(TEXT_SHORT));
 | |
|         h.append_move(std::string(TEXT_LONG));
 | |
|         h.append_move(123);
 | |
|         h.append_move(3.14159);
 | |
|     }
 | |
| 
 | |
|     boost::variant<int, double, std::string> v;
 | |
|     for (auto const& v2 : h.data)
 | |
|     {
 | |
|         dummy<boost::variant<int, double, std::string>> d(v);
 | |
|         boost::apply_visitor(d, v2);
 | |
|     }
 | |
| }
 | |
| 
 | |
| void run_variant_test(std::size_t runs)
 | |
| {
 | |
|     test::Holder<util::variant<int, double, std::string>> h;
 | |
|     h.data.reserve(runs);
 | |
|     for (std::size_t i = 0; i < runs; ++i)
 | |
|     {
 | |
|         h.append_move(std::string(TEXT_SHORT));
 | |
|         h.append_move(std::string(TEXT_LONG));
 | |
|         h.append_move(123);
 | |
|         h.append_move(3.14159);
 | |
|     }
 | |
| 
 | |
|     util::variant<int, double, std::string> v;
 | |
|     for (auto const& v2 : h.data)
 | |
|     {
 | |
|         dummy2<util::variant<int, double, std::string>> d(v);
 | |
|         util::apply_visitor(d, v2);
 | |
|     }
 | |
| }
 | |
| 
 | |
| int main(int argc, char** argv)
 | |
| {
 | |
|     if (argc != 2)
 | |
|     {
 | |
|         std::cerr << "Usage:" << argv[0] << " <num-runs>" << std::endl;
 | |
|         return 1;
 | |
|     }
 | |
| 
 | |
| #ifndef SINGLE_THREADED
 | |
|     const std::size_t THREADS = 4;
 | |
| #endif
 | |
|     const std::size_t NUM_RUNS = static_cast<std::size_t>(std::stol(argv[1]));
 | |
| 
 | |
| #ifdef SINGLE_THREADED
 | |
| 
 | |
|     for (std::size_t j = 0; j < NUM_SAMPLES; ++j)
 | |
|     {
 | |
| 
 | |
|         {
 | |
|             std::cerr << "custom variant: ";
 | |
|             auto_cpu_timer t;
 | |
|             run_variant_test(NUM_RUNS);
 | |
|         }
 | |
|         {
 | |
|             std::cerr << "boost variant: ";
 | |
|             auto_cpu_timer t;
 | |
|             run_boost_test(NUM_RUNS);
 | |
|         }
 | |
|     }
 | |
| 
 | |
| #else
 | |
|     for (std::size_t j = 0; j < NUM_SAMPLES; ++j)
 | |
|     {
 | |
|         {
 | |
|             typedef std::vector<std::unique_ptr<std::thread>> thread_group;
 | |
|             typedef thread_group::value_type value_type;
 | |
|             thread_group tg;
 | |
|             std::cerr << "custom variant: ";
 | |
|             auto_cpu_timer timer;
 | |
|             for (std::size_t i = 0; i < THREADS; ++i)
 | |
|             {
 | |
|                 tg.emplace_back(new std::thread(run_variant_test, NUM_RUNS));
 | |
|             }
 | |
|             std::for_each(tg.begin(), tg.end(), [](value_type& t) {if (t->joinable()) t->join(); });
 | |
|         }
 | |
| 
 | |
|         {
 | |
|             typedef std::vector<std::unique_ptr<std::thread>> thread_group;
 | |
|             typedef thread_group::value_type value_type;
 | |
|             thread_group tg;
 | |
|             std::cerr << "boost variant: ";
 | |
|             auto_cpu_timer timer;
 | |
|             for (std::size_t i = 0; i < THREADS; ++i)
 | |
|             {
 | |
|                 tg.emplace_back(new std::thread(run_boost_test, NUM_RUNS));
 | |
|             }
 | |
|             std::for_each(tg.begin(), tg.end(), [](value_type& t) {if (t->joinable()) t->join(); });
 | |
|         }
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     return EXIT_SUCCESS;
 | |
| }
 |