1 /* 2 * SObjectizer-5 3 */ 4 /*! 5 * \since v.5.4.0 6 * \file 7 * \brief A simple helpers for building benchmarks. 8 */ 9 #pragma once 10 11 #include <chrono> 12 #include <iostream> 13 #include <string> 14 #include <stdexcept> 15 16 namespace benchmarks_details { 17 18 //! Helper class for changing and restoring ostream precision settings. 19 class precision_settings_t 20 { 21 std::ios_base & m_what; 22 std::streamsize m_old_value; 23 24 public : precision_settings_t(std::ios_base & what,std::streamsize new_value)25 precision_settings_t( 26 std::ios_base & what, 27 std::streamsize new_value ) 28 : m_what( what ) 29 , m_old_value( what.precision( new_value ) ) 30 {} ~precision_settings_t()31 ~precision_settings_t() 32 { 33 m_what.precision( m_old_value ); 34 } 35 }; 36 37 } /* namespace benchmarks_details */ 38 39 //! A helper for fixing starting and finishing time points and 40 //! calculate events processing time and events throughtput. 41 class benchmarker_t 42 { 43 public : 44 //! Fix starting time. 45 inline void start()46 start() 47 { 48 m_start = std::chrono::high_resolution_clock::now(); 49 } 50 51 //! Fix finish time and show stats. 52 inline void finish_and_show_stats(unsigned long long events,const std::string & title)53 finish_and_show_stats( 54 unsigned long long events, 55 const std::string & title ) 56 { 57 if( !events ) 58 throw std::invalid_argument( "events cannot be 0" ); 59 60 auto finish_time = std::chrono::high_resolution_clock::now(); 61 const double duration = 62 std::chrono::duration_cast< std::chrono::milliseconds >( 63 finish_time - m_start ).count() / 1000.0; 64 const double price = duration / events; 65 const double throughtput = 1 / price; 66 67 benchmarks_details::precision_settings_t precision{ std::cout, 10 }; 68 std::cout << title << ": " << events 69 << ", total_time: " << duration << "s" 70 << "\n""price: " << price << "s" 71 << "\n""throughtput: " << throughtput << " " << title << "/s" 72 << std::endl; 73 } 74 75 private : 76 std::chrono::high_resolution_clock::time_point m_start; 77 }; 78 79 //! A helper for showing duration between constructor and destructor calls. 80 /*! 81 * Usage example: 82 \code 83 { 84 duration_meter_t meter( "creating some objects" ); 85 ... // Some code here 86 } // Duration of the code above will be shown here. 87 \endcode 88 */ 89 class duration_meter_t 90 { 91 public : duration_meter_t(std::string name)92 duration_meter_t( std::string name ) 93 : m_name( std::move( name ) ) 94 , m_start( std::chrono::high_resolution_clock::now() ) 95 {} 96 ~duration_meter_t()97 ~duration_meter_t() 98 { 99 auto finish = std::chrono::high_resolution_clock::now(); 100 101 benchmarks_details::precision_settings_t precision{ std::cout, 10 }; 102 std::cout << m_name << ": " 103 << std::chrono::duration_cast< std::chrono::milliseconds >( 104 finish - m_start ).count() / 1000.0 << "s" 105 << std::endl; 106 } 107 108 private : 109 const std::string m_name; 110 const std::chrono::high_resolution_clock::time_point m_start; 111 }; 112 113