00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00033
00034 #ifndef GROOVX_RUTZ_PROF_CC_UTC20050630214713_DEFINED
00035 #define GROOVX_RUTZ_PROF_CC_UTC20050630214713_DEFINED
00036
00037 #include "rutz/prof.h"
00038
00039 #include "rutz/abort.h"
00040 #include "rutz/mutex.h"
00041 #include "rutz/staticstack.h"
00042
00043 #include <algorithm>
00044 #include <cstdio>
00045 #include <functional>
00046 #include <iomanip>
00047 #include <new>
00048 #include <ostream>
00049 #include <pthread.h>
00050 #include <string>
00051
00052 namespace
00053 {
00054
00055
00056
00057
00058 bool g_pdata_print_at_exit = false;
00059 std::string g_pdata_fname = "prof.out";
00060 FILE* g_pdata_file = 0;
00061 pthread_once_t g_pdata_file_once = PTHREAD_ONCE_INIT;
00062 pthread_mutex_t g_pdata_mutex = PTHREAD_MUTEX_INITIALIZER;
00063
00064 void open_pdata_file()
00065 {
00066 if (g_pdata_fname.length() > 0)
00067 g_pdata_file = fopen(g_pdata_fname.c_str(), "w");
00068
00069 if (g_pdata_file == 0)
00070 {
00071 fprintf(stderr,
00072 "couldn't open profile file '%s' for writing\n",
00073 g_pdata_fname.c_str());
00074 }
00075 }
00076
00077
00078
00079
00080
00081 typedef rutz::static_stack<rutz::prof*, 2048> prof_list;
00082
00083 prof_list* g_prof_list = 0;
00084 pthread_once_t g_prof_list_once = PTHREAD_ONCE_INIT;
00085 pthread_mutex_t g_prof_list_mutex = PTHREAD_MUTEX_INITIALIZER;
00086
00087 void initialize_prof_list()
00088 {
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101 g_prof_list = new (std::nothrow) prof_list;
00102
00103 if (g_prof_list == 0)
00104 GVX_ABORT("memory allocation failed");
00105 }
00106
00107 prof_list& all_profs() throw()
00108 {
00109 pthread_once(&g_prof_list_once, &initialize_prof_list);
00110
00111 return *g_prof_list;
00112 }
00113
00114
00115
00116
00117
00118 rutz::time g_start;
00119 pthread_once_t g_start_once = PTHREAD_ONCE_INIT;
00120
00121 void initialize_start_time()
00122 {
00123 g_start = rutz::prof::get_now_time(rutz::prof::get_timing_mode());
00124 }
00125 }
00126
00128
00129
00130
00132
00133 rutz::prof::timing_mode rutz::prof::s_timing_mode = rutz::prof::RUSAGE;
00134
00135 rutz::prof::prof(const char* s, const char* fname, int lineno) throw():
00136 m_context_name(s),
00137 m_src_file_name(fname),
00138 m_src_line_no(lineno)
00139 {
00140 reset();
00141
00142 {
00143 GVX_MUTEX_LOCK(&g_prof_list_mutex);
00144 all_profs().push(this);
00145 }
00146
00147 pthread_once(&g_start_once, &initialize_start_time);
00148 }
00149
00150 rutz::prof::~prof() throw()
00151 {
00152 if (g_pdata_print_at_exit)
00153 {
00154 pthread_once(&g_pdata_file_once, &open_pdata_file);
00155
00156 GVX_MUTEX_LOCK(&g_pdata_mutex);
00157
00158 if (g_pdata_file != 0)
00159 {
00160 print_prof_data(g_pdata_file);
00161 }
00162 }
00163 }
00164
00165 void rutz::prof::reset() throw()
00166 {
00167 m_call_count = 0;
00168 m_total_time.reset();
00169 m_children_time.reset();
00170 }
00171
00172 unsigned int rutz::prof::count() const throw()
00173 {
00174 return m_call_count;
00175 }
00176
00177 void rutz::prof::add_time(const rutz::time& t) throw()
00178 {
00179 m_total_time += t;
00180 ++m_call_count;
00181 }
00182
00183 void rutz::prof::add_child_time(const rutz::time& t) throw()
00184 {
00185 m_children_time += t;
00186 }
00187
00188 const char* rutz::prof::context_name() const throw()
00189 {
00190 return m_context_name;
00191 }
00192
00193 const char* rutz::prof::src_file_name() const throw()
00194 {
00195 return m_src_file_name;
00196 }
00197
00198 int rutz::prof::src_line_no() const throw()
00199 {
00200 return m_src_line_no;
00201 }
00202
00203 double rutz::prof::total_time() const throw()
00204 {
00205 return (m_call_count > 0)
00206 ? m_total_time.usec()
00207 : 0.0;
00208 }
00209
00210 double rutz::prof::self_time() const throw()
00211 {
00212 return (m_call_count > 0)
00213 ? m_total_time.usec() - m_children_time.usec()
00214 : 0.0;
00215 }
00216
00217 double rutz::prof::avg_self_time() const throw()
00218 {
00219 return m_call_count > 0 ? (total_time() / m_call_count) : 0.0;
00220 }
00221
00222 void rutz::prof::print_prof_data(FILE* file) const throw()
00223 {
00224 if (file == 0)
00225 GVX_ABORT("FILE* was null");
00226
00227 const double total_elapsed_usec =
00228 (rutz::prof::get_now_time(s_timing_mode) - g_start).usec();
00229
00230
00231
00232
00233 fprintf(file, "%10.0f %6u %10.0f %4.1f%% %10.0f %4.1f%% %s\n",
00234 avg_self_time(), count(),
00235 self_time(), (100.0 * self_time()) / total_elapsed_usec,
00236 total_time(), (100.0 * total_time()) / total_elapsed_usec,
00237 m_context_name);
00238 }
00239
00240 void rutz::prof::print_prof_data(std::ostream& os) const throw()
00241 {
00242 os.exceptions(std::ios::goodbit);
00243
00244 const double total_elapsed_usec =
00245 (rutz::prof::get_now_time(s_timing_mode) - g_start).usec();
00246
00247
00248
00249
00250 os << std::fixed
00251 << std::setw(10) << std::setprecision(0) << avg_self_time() << ' '
00252 << std::setw(6) << count() << ' '
00253 << std::setw(10) << std::setprecision(0) << self_time() << ' '
00254 << std::setw(4) << std::setprecision(1)
00255 << (100.0 * self_time()) / total_elapsed_usec << "% "
00256 << std::setw(10) << std::setprecision(0) << total_time() << ' '
00257 << std::setw(4) << std::setprecision(1)
00258 << (100.0 * total_time()) / total_elapsed_usec << "% "
00259 << m_context_name << '\n';
00260 }
00261
00262 void rutz::prof::print_at_exit(bool yes_or_no) throw()
00263 {
00264 g_pdata_print_at_exit = yes_or_no;
00265 }
00266
00267 void rutz::prof::prof_summary_file_name(const char* fname)
00268 {
00269 GVX_MUTEX_LOCK(&g_pdata_mutex);
00270
00271 if (fname == 0)
00272 fname = "";
00273
00274 g_pdata_fname = fname;
00275 }
00276
00277 void rutz::prof::reset_all_prof_data() throw()
00278 {
00279 GVX_MUTEX_LOCK(&g_prof_list_mutex);
00280 std::for_each(all_profs().begin(), all_profs().end(),
00281 std::mem_fun(&rutz::prof::reset));
00282 }
00283
00284 namespace
00285 {
00286
00287 bool compare_total_time(rutz::prof* p1, rutz::prof* p2) throw()
00288 {
00289 return p1->total_time() < p2->total_time();
00290 }
00291 }
00292
00293 void rutz::prof::print_all_prof_data(FILE* file) throw()
00294 {
00295 GVX_MUTEX_LOCK(&g_prof_list_mutex);
00296 std::stable_sort(all_profs().begin(), all_profs().end(),
00297 compare_total_time);
00298
00299 for (unsigned int i = 0; i < all_profs().size(); ++i)
00300 {
00301 if (all_profs()[i]->count() > 0)
00302 all_profs()[i]->print_prof_data(file);
00303 }
00304 }
00305
00306 void rutz::prof::print_all_prof_data(std::ostream& os) throw()
00307 {
00308 GVX_MUTEX_LOCK(&g_prof_list_mutex);
00309 std::stable_sort(all_profs().begin(), all_profs().end(),
00310 compare_total_time);
00311
00312 for (unsigned int i = 0; i < all_profs().size(); ++i)
00313 {
00314 if (all_profs()[i]->count() > 0)
00315 all_profs()[i]->print_prof_data(os);
00316 }
00317 }
00318
00319 static const char __attribute__((used)) vcid_groovx_rutz_prof_cc_utc20050630214713[] = "$Id: prof.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00320 #endif // !GROOVX_RUTZ_PROF_CC_UTC20050630214713DEFINED