1 // -*- C++ -*- 2 // Testing performance utilities for the C++ library testsuite. 3 // 4 // Copyright (C) 2003 Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 2, or (at your option) 10 // any later version. 11 // 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 // 17 // You should have received a copy of the GNU General Public License along 18 // with this library; see the file COPYING. If not, write to the Free 19 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, 20 // USA. 21 // 22 // As a special exception, you may use this file as part of a free software 23 // library without restriction. Specifically, if other files instantiate 24 // templates or use macros or inline functions from this file, or you compile 25 // this file and link it with other files to produce an executable, this 26 // file does not by itself cause the resulting executable to be covered by 27 // the GNU General Public License. This exception does not however 28 // invalidate any other reasons why the executable file might be covered by 29 // the GNU General Public License. 30 31 #ifndef _GLIBCXX_PERFORMANCE_H 32 #define _GLIBCXX_PERFORMANCE_H 33 34 #include <sys/times.h> 35 #include <sys/resource.h> 36 #include <cstdlib> 37 #include <string> 38 #include <fstream> 39 #include <iomanip> 40 41 #ifdef __linux__ 42 #include <malloc.h> 43 #elif defined (__FreeBSD__) 44 extern "C" 45 { 46 struct mallinfo 47 { 48 int uordblks; 49 int hblkhd; 50 }; 51 52 struct mallinfo mallinfo(void)53 mallinfo(void) 54 { 55 struct mallinfo m = { (((size_t) sbrk (0) + 1023) / 1024), 0 }; 56 return m; 57 } 58 } 59 #else 60 extern "C" 61 { 62 struct mallinfo 63 { 64 int uordblks; 65 int hblkhd; 66 }; 67 68 struct mallinfo empty = { 0, 0 }; 69 70 struct mallinfo mallinfo(void)71 mallinfo(void) 72 { return empty; } 73 } 74 #endif 75 76 namespace __gnu_test 77 { 78 class time_counter 79 { 80 clock_t elapsed_begin; 81 clock_t elapsed_end; 82 tms tms_begin; 83 tms tms_end; 84 85 public: time_counter()86 time_counter() 87 { this->clear(); } 88 89 void clear()90 clear() 91 { 92 elapsed_begin = 0; 93 elapsed_end = 0; 94 memset(&tms_begin, 0, sizeof(tms)); 95 memset(&tms_end, 0, sizeof(tms)); 96 } 97 98 void start()99 start() 100 { elapsed_begin = times(&tms_begin); } 101 102 void stop()103 stop() 104 { elapsed_end = times(&tms_end); } 105 106 size_t real_time()107 real_time() const 108 { return elapsed_end - elapsed_begin; } 109 110 size_t user_time()111 user_time() const 112 { return tms_end.tms_utime - tms_begin.tms_utime; } 113 114 size_t system_time()115 system_time() const 116 { return tms_end.tms_stime - tms_begin.tms_stime; } 117 }; 118 119 class resource_counter 120 { 121 int who; 122 rusage rusage_begin; 123 rusage rusage_end; 124 struct mallinfo allocation_begin; 125 struct mallinfo allocation_end; 126 127 public: who(i)128 resource_counter(int i = RUSAGE_SELF) : who(i) 129 { this->clear(); } 130 131 void clear()132 clear() 133 { 134 memset(&rusage_begin, 0, sizeof(rusage_begin)); 135 memset(&rusage_end, 0, sizeof(rusage_end)); 136 memset(&allocation_begin, 0, sizeof(allocation_begin)); 137 memset(&allocation_end, 0, sizeof(allocation_end)); 138 } 139 140 void start()141 start() 142 { 143 if (getrusage(who, &rusage_begin) != 0 ) 144 memset(&rusage_begin, 0, sizeof(rusage_begin)); 145 malloc(0); // Needed for some implementations. 146 allocation_begin = mallinfo(); 147 } 148 149 void stop()150 stop() 151 { 152 if (getrusage(who, &rusage_end) != 0 ) 153 memset(&rusage_end, 0, sizeof(rusage_end)); 154 allocation_end = mallinfo(); 155 } 156 157 int allocated_memory()158 allocated_memory() const 159 { return ((allocation_end.uordblks - allocation_begin.uordblks) 160 + (allocation_end.hblkhd - allocation_begin.hblkhd)); } 161 162 long hard_page_fault()163 hard_page_fault() const 164 { return rusage_end.ru_majflt - rusage_begin.ru_majflt; } 165 166 long swapped()167 swapped() const 168 { return rusage_end.ru_nswap - rusage_begin.ru_nswap; } 169 }; 170 171 void start_counters(time_counter & t,resource_counter & r)172 start_counters(time_counter& t, resource_counter& r) 173 { 174 t.start(); 175 r.start(); 176 } 177 178 void stop_counters(time_counter & t,resource_counter & r)179 stop_counters(time_counter& t, resource_counter& r) 180 { 181 t.stop(); 182 r.stop(); 183 } 184 185 void clear_counters(time_counter & t,resource_counter & r)186 clear_counters(time_counter& t, resource_counter& r) 187 { 188 t.clear(); 189 r.clear(); 190 } 191 192 void report_performance(const std::string file,const std::string comment,const time_counter & t,const resource_counter & r)193 report_performance(const std::string file, const std::string comment, 194 const time_counter& t, const resource_counter& r) 195 { 196 const char space = ' '; 197 const char tab = '\t'; 198 const char* name = "libstdc++-performance.sum"; 199 std::string::const_iterator i = file.begin() + file.find_last_of('/') + 1; 200 std::string testname(i, file.end()); 201 202 std::ofstream out(name, std::ios_base::app); 203 204 #ifdef __GTHREADS 205 if (__gthread_active_p ()) 206 testname.append ("-thread"); 207 #endif 208 209 out.setf(std::ios_base::left); 210 out << std::setw(25) << testname << tab; 211 out << std::setw(25) << comment << tab; 212 213 out.setf(std::ios_base::right); 214 out << std::setw(4) << t.real_time() << "r" << space; 215 out << std::setw(4) << t.user_time() << "u" << space; 216 out << std::setw(4) << t.system_time() << "s" << space; 217 out << std::setw(8) << r.allocated_memory() << "mem" << space; 218 out << std::setw(4) << r.hard_page_fault() << "pf" << space; 219 220 out << std::endl; 221 out.close(); 222 } 223 224 void report_header(const std::string file,const std::string header)225 report_header(const std::string file, const std::string header) 226 { 227 const char space = ' '; 228 const char tab = '\t'; 229 const char* name = "libstdc++-performance.sum"; 230 std::string::const_iterator i = file.begin() + file.find_last_of('/') + 1; 231 std::string testname(i, file.end()); 232 233 std::ofstream out(name, std::ios_base::app); 234 235 #ifdef __GTHREADS 236 if (__gthread_active_p ()) 237 testname.append ("-thread"); 238 #endif 239 240 out.setf(std::ios_base::left); 241 out << std::setw(25) << testname << tab; 242 out << std::setw(40) << header << tab; 243 244 out << std::endl; 245 out.close(); 246 } 247 }; // namespace __gnu_test 248 249 #endif // _GLIBCXX_PERFORMANCE_H 250 251