|
| 1 | +// Copyright 2018 Diffblue Limited. All Rights Reserved. |
| 2 | + |
| 3 | +/// \file |
| 4 | +/// Micro time profiler with code block granularity. |
| 5 | + |
1 | 6 | #ifndef CPROVER_SECURITY_ANALYSER_UTIL_TMPROF_H
|
2 | 7 | #define CPROVER_SECURITY_ANALYSER_UTIL_TMPROF_H
|
3 | 8 |
|
4 | 9 | #include <util/json.h>
|
5 | 10 | #include <boost/filesystem/path.hpp>
|
| 11 | +#include <list> |
6 | 12 | #include <chrono>
|
7 | 13 | #include <string>
|
8 |
| -#include <list> |
9 |
| -#include <iostream> |
| 14 | +#include <iosfwd> |
10 | 15 |
|
11 |
| -/// Usage: |
12 |
| -/// In order to measure a time performance of a C++ block of code |
13 |
| -/// simply place 'TMPROF_BLOCK();' at the beginning of the block. |
14 |
| -/// (Do not forget to include this header file to the module.) |
15 |
| -/// Example: |
| 16 | +/// \remarks |
| 17 | +/// Usage: |
| 18 | +/// In order to measure a time performance of a C++ block of code |
| 19 | +/// simply place 'TMPROF_BLOCK();' at the beginning of the block. |
| 20 | +/// (Do not forget to include this header file to the module.) |
| 21 | +/// \remarks |
| 22 | +/// Example: |
16 | 23 | /// Let us assume you add TMPROF_BLOCK() calls to function 'foo()' as follows:
|
| 24 | +/// \code |
17 | 25 | /// 1 void foo()
|
18 | 26 | /// 2 {
|
19 | 27 | /// 3 TMPROF_BLOCK(); // This one will give us statistic of whole foo(),
|
|
31 | 39 | /// 15
|
32 | 40 | /// 16 int main()
|
33 | 41 | /// 17 {
|
34 |
| -//// 18 foo(); |
| 42 | +/// 18 foo(); |
35 | 43 | /// 19 tmprof_dump_in_json(std::cout);
|
36 | 44 | /// 20 }
|
| 45 | +/// \endcode |
37 | 46 | /// Then, the program will print to 'std::cout' JSON on this form:
|
| 47 | +/// \code |
38 | 48 | /// {
|
39 | 49 | /// {
|
40 | 50 | /// "foo [3]": {
|
|
49 | 59 | /// "total_time": 50
|
50 | 60 | /// },
|
51 | 61 | /// },
|
52 |
| -/// NOTE: Recursive calls are trait as independent ones. |
53 |
| -/// NOTE: A C++ code block may have at most one TMPROF_BLOCK() call. |
54 |
| -/// NOTE: The implementation is NOT thread-safe. |
55 |
| -/// NOTE: You can temporarily disable time-profiler by calling: |
56 |
| -/// enable_time_profiling(false); |
57 |
| -/// To check enable/disable state of the time-profiler call: |
58 |
| -/// is_time_profiling_enabled(); |
59 |
| -/// The time-profiler is enabled by default. |
| 62 | +/// \endcode |
| 63 | +/// \remarks |
| 64 | +/// In order to activate the system you need to set the value of the |
| 65 | +/// macro TMPROF_ENABLED below to 1. |
| 66 | +/// \remarks |
| 67 | +/// Recursive calls are treated as independent ones. |
| 68 | +/// \remarks |
| 69 | +/// A C++ code block may have at most one TMPROF_BLOCK() call. |
| 70 | +/// \remarks |
| 71 | +/// The implementation is NOT thread-safe. |
| 72 | +/// \remarks |
| 73 | +/// You can temporarily disable time-profiler by calling: |
| 74 | +/// enable_time_profiling(false); |
| 75 | +/// To check enable/disable state of the time-profiler call: |
| 76 | +/// is_time_profiling_enabled(); |
| 77 | +/// The time-profiler is enabled by default. |
60 | 78 |
|
| 79 | +//#define TMPROF_ENABLED |
| 80 | +#ifdef TMPROF_ENABLED |
61 | 81 | #define TMPROF_BLOCK() \
|
62 |
| - static __tmprof_detail_data* const __tmprof_detail_record_ptr = \ |
63 |
| - __tmprof_detail_add_record(__tmprof_detail_data(__FUNCTION__,__LINE__)); \ |
64 |
| - const __tmprof_detail_on_hit __tmprof_detail_hit( \ |
65 |
| - is_time_profiling_enabled() ? __tmprof_detail_record_ptr : nullptr) |
| 82 | + static tmprof_detail_datat *const __tmprof_detail_record_ptr = \ |
| 83 | + tmprof_detail_datat::create(__FUNCTION__, __LINE__); \ |
| 84 | + const tmprof_detail_on_hitt __tmprof_detail_hit(__tmprof_detail_record_ptr) |
| 85 | +#else |
| 86 | +#define TMPROF_BLOCK() |
| 87 | +#endif |
66 | 88 |
|
67 | 89 | bool is_time_profiling_enabled();
|
68 |
| -void enable_time_profiling(const bool state); |
| 90 | +void enable_time_profiling(const bool state = true); |
69 | 91 |
|
70 |
| -void tmprof_dump_in_json(std::ostream &ostr); |
71 |
| -void tmprof_dump_in_json(const boost::filesystem::path &out_file_pathname); |
| 92 | +void tmprof_dump_as_json(std::ostream &ostr); |
| 93 | +void tmprof_dump_as_json(const boost::filesystem::path &out_file_pathname); |
72 | 94 |
|
73 | 95 | // Next follow PRIVATE IMPLEMENTATION DETAILS. Do not use them directly !!!
|
74 | 96 |
|
75 |
| -struct __tmprof_detail_data |
| 97 | +struct tmprof_detail_datat |
76 | 98 | {
|
77 |
| - __tmprof_detail_data(const std::string &name, const unsigned long line) |
| 99 | + static tmprof_detail_datat * |
| 100 | + create(const char *name, const unsigned long line); |
| 101 | + |
| 102 | + tmprof_detail_datat(const char *const name, const unsigned long line) |
78 | 103 | : name(name), line(line), total_time(0.0), max_time(0.0), hit_count(0ULL)
|
79 | 104 | {
|
80 | 105 | }
|
81 | 106 |
|
82 |
| - std::string name; |
83 |
| - unsigned long line; |
| 107 | + const char *get_name() const |
| 108 | + { |
| 109 | + return name; |
| 110 | + } |
| 111 | + |
| 112 | + const unsigned long get_line() const |
| 113 | + { |
| 114 | + return line; |
| 115 | + } |
| 116 | + |
| 117 | + double get_total_time() const |
| 118 | + { |
| 119 | + return total_time; |
| 120 | + } |
| 121 | + |
| 122 | + double get_max_time() const |
| 123 | + { |
| 124 | + return max_time; |
| 125 | + } |
| 126 | + |
| 127 | + unsigned long long get_hit_count() const |
| 128 | + { |
| 129 | + return hit_count; |
| 130 | + } |
| 131 | + |
| 132 | + void on_hit(const double duration); |
| 133 | + |
| 134 | + static json_objectt dump_as_json(); |
| 135 | + |
| 136 | +private: |
| 137 | + const char *name; |
| 138 | + const unsigned long line; |
84 | 139 | double total_time;
|
85 | 140 | double max_time;
|
86 | 141 | unsigned long long hit_count;
|
| 142 | + |
| 143 | + static std::list<tmprof_detail_datat> records; |
87 | 144 | };
|
88 | 145 |
|
89 |
| -struct __tmprof_detail_on_hit |
| 146 | +struct tmprof_detail_on_hitt |
90 | 147 | {
|
91 |
| - explicit __tmprof_detail_on_hit(__tmprof_detail_data *const data) |
| 148 | + explicit tmprof_detail_on_hitt(tmprof_detail_datat *const data) |
92 | 149 | : data(data), start_time(std::chrono::high_resolution_clock::now())
|
93 | 150 | {
|
94 | 151 | }
|
95 |
| - ~__tmprof_detail_on_hit() |
| 152 | + ~tmprof_detail_on_hitt() |
96 | 153 | {
|
97 |
| - if(data != nullptr) |
| 154 | + if(is_time_profiling_enabled()) |
98 | 155 | {
|
99 | 156 | auto const duration =
|
100 | 157 | std::chrono::duration<double>(
|
101 | 158 | std::chrono::high_resolution_clock::now() - start_time)
|
102 | 159 | .count();
|
103 |
| - data->total_time += duration; |
104 |
| - if(data->max_time < duration) |
105 |
| - data->max_time = duration; |
106 |
| - ++data->hit_count; |
| 160 | + data->on_hit(duration); |
107 | 161 | }
|
108 | 162 | }
|
109 |
| - __tmprof_detail_data *data; |
| 163 | + |
| 164 | +private: |
| 165 | + tmprof_detail_datat *data; |
110 | 166 | std::chrono::high_resolution_clock::time_point start_time;
|
111 | 167 | };
|
112 | 168 |
|
113 |
| -__tmprof_detail_data * |
114 |
| -__tmprof_detail_add_record(const __tmprof_detail_data &data); |
115 |
| - |
116 | 169 | #endif //CPROVER_SECURITY_ANALYSER_UTIL_TMPROF_H
|
0 commit comments