1 2using namespace std; 3 4#include <sys/time.h> 5#ifdef OS2 6#define INCL_DOSFILEMGR 7#define INCL_BASE 8#include <os2.h> 9#include "os2-perfutil.h" 10/* 11 Convert 8-byte (low, high) time value to double 12*/ 13#define LL2F(high, low) (4294967296.0*(high)+(low)) 14#else 15#include <unistd.h> 16#include <sys/resource.h> 17#endif 18#include "bon_time.h" 19#include <time.h> 20#include <string.h> 21 22#ifndef NON_UNIX 23#include "conf.h" 24#endif 25 26#ifdef HAVE_ALGORITHM 27#include <algorithm> 28#else 29 30#ifdef HAVE_ALGO 31#include <algo> 32#else 33#ifdef HAVE_ALGO_H 34#include <algo.h> 35#else 36#define min(XX,YY) ((XX) < (YY) ? (XX) : (YY)) 37#define max(XX,YY) ((XX) > (YY) ? (XX) : (YY)) 38#endif 39#endif 40 41#endif 42 43#define TIMEVAL_TO_DOUBLE(XX) (double((XX).tv_sec) + double((XX).tv_usec) / 1000000.0) 44 45void BonTimer::timestamp() 46{ 47 m_last_timestamp = get_cur_time(); 48 m_last_cpustamp = get_cpu_use(); 49} 50 51double 52BonTimer::time_so_far() 53{ 54 return get_cur_time() - m_last_timestamp; 55} 56 57double 58BonTimer::cpu_so_far() 59{ 60 return get_cpu_use() - m_last_cpustamp; 61} 62 63double 64BonTimer::get_cur_time() 65{ 66#ifdef OS2 67 ULONG count = 0; 68 ULONG rc = DosQuerySysInfo(QSV_MS_COUNT, QSV_MS_COUNT, &count, sizeof(count)); 69 if(rc) 70 return 0.0; 71 return double(count)/1000.0; 72#else 73 struct timeval tp; 74 75 if (gettimeofday(&tp, static_cast<struct timezone *>(NULL)) == -1) 76 io_error("gettimeofday", true); 77 return TIMEVAL_TO_DOUBLE(tp); 78#endif 79} 80 81double 82BonTimer::get_cpu_use() 83{ 84#ifdef OS2 85 double busy_val, busy_val_prev; 86 double intr_val, intr_val_prev; 87 CPUUTIL CPUUtil; 88 89 ULONG rc = DosPerfSysCall(CMD_KI_RDCNT,(ULONG) &CPUUtil,0,0); 90 if(rc) 91 io_error("times", true); 92 return LL2F(CPUUtil.ulBusyHigh, CPUUtil.ulBusyLow) 93 + LL2F(CPUUtil.ulIntrHigh, CPUUtil.ulIntrLow); 94#else 95 struct rusage res_usage; 96 97 getrusage(RUSAGE_SELF, &res_usage); 98 return TIMEVAL_TO_DOUBLE(res_usage.ru_utime) + TIMEVAL_TO_DOUBLE(res_usage.ru_stime); 99#endif 100} 101 102void BonTimer::get_delta_t(tests_t test) 103{ 104 m_delta[test].Elapsed = time_so_far(); 105 m_delta[test].CPU = cpu_so_far(); 106 timestamp(); 107} 108 109void BonTimer::get_delta_report(report_s &rep) 110{ 111 rep.EndTime = get_cur_time(); 112 rep.CPU = cpu_so_far(); 113 timestamp(); 114} 115 116void BonTimer::add_delta_report(report_s &rep, tests_t test) 117{ 118 if(m_delta[test].CPU == 0.0) 119 { 120 m_delta[test].FirstStart = rep.StartTime; 121 m_delta[test].LastStop = rep.EndTime; 122 } 123 else 124 { 125 m_delta[test].FirstStart = min(m_delta[test].FirstStart, rep.StartTime); 126 m_delta[test].LastStop = max(m_delta[test].LastStop, rep.EndTime); 127 } 128 m_delta[test].CPU += rep.CPU; 129 m_delta[test].Elapsed = m_delta[test].LastStop - m_delta[test].FirstStart; 130} 131 132BonTimer::BonTimer() 133 : m_type(txt) 134{ 135 Initialize(); 136} 137 138void 139BonTimer::Initialize() 140{ 141 for(int i = 0; i < TestCount; i++) 142 { 143 m_delta[i].CPU = 0.0; 144 m_delta[i].Elapsed = 0.0; 145 } 146 timestamp(); 147} 148 149int BonTimer::print_cpu_stat(tests_t test) 150{ 151 if(m_delta[test].Elapsed == 0.0) 152 { 153 if(m_type == txt) 154 fprintf(m_fp, " "); 155 else 156 fprintf(m_fp, ","); 157 return 0; 158 } 159 if(m_delta[test].Elapsed < MinTime) 160 { 161 if(m_type == txt) 162 fprintf(m_fp, " +++"); 163 else 164 fprintf(m_fp, ",+++"); 165 return 0; 166 } 167 int cpu = int(m_delta[test].CPU / m_delta[test].Elapsed * 100.0); 168 if(m_type == txt) 169 fprintf(m_fp, " %3d", cpu); 170 else 171 fprintf(m_fp, ",%d", cpu); 172 return 0; 173} 174 175int BonTimer::print_stat(tests_t test) 176{ 177 if(m_delta[test].Elapsed == 0.0) 178 { 179 if(m_type == txt) 180 fprintf(m_fp, " "); 181 else 182 fprintf(m_fp, ","); 183 } 184 else if(m_delta[test].Elapsed < MinTime) 185 { 186 if(m_type == txt) 187 fprintf(m_fp, " +++++"); 188 else 189 fprintf(m_fp, ",+++++"); 190 } 191 else 192 { 193 if(test == Lseek) 194 { 195 double seek_stat = double(Seeks) / m_delta[test].Elapsed; 196 if(m_type == txt) 197 { 198 if(seek_stat >= 1000.0) 199 fprintf(m_fp, " %5.0f", seek_stat); 200 else 201 fprintf(m_fp, " %5.1f", seek_stat); 202 } 203 else 204 fprintf(m_fp, ",%.1f", seek_stat); 205 } 206 else 207 { 208 int res = int(double(m_file_size) / (m_delta[test].Elapsed / 1024.0)); 209 if(m_type == txt) 210 fprintf(m_fp, " %5d", res); 211 else 212 fprintf(m_fp, ",%d", res); 213 } 214 } 215 return print_cpu_stat(test); 216} 217 218int BonTimer::print_file_stat(tests_t test) 219{ 220 if(m_delta[test].Elapsed == 0.0) 221 { 222 if(m_type == txt) 223 fprintf(m_fp, " "); 224 else 225 fprintf(m_fp, ","); 226 } 227 else if(m_delta[test].Elapsed < MinTime) 228 { 229 if(m_type == txt) 230 fprintf(m_fp, " +++++"); 231 else 232 fprintf(m_fp, ",+++++"); 233 } 234 else 235 { 236 int res = int(double(m_directory_size) * double(DirectoryUnit) 237 / m_delta[test].Elapsed); 238 if(m_type == txt) 239 fprintf(m_fp, " %5d", res); 240 else 241 fprintf(m_fp, ",%d", res); 242 } 243 244 return print_cpu_stat(test); 245} 246 247void 248BonTimer::PrintHeader(FILE *fp) 249{ 250 fprintf(fp, "name"); 251 fprintf(fp, ",file_size,putc,putc_cpu,put_block,put_block_cpu,rewrite,rewrite_cpu,getc,getc_cpu,get_block,get_block_cpu,seeks,seeks_cpu"); 252 fprintf(fp, ",num_files,seq_create,seq_create_cpu,seq_stat,seq_stat_cpu,seq_del,seq_del_cpu,ran_create,ran_create_cpu,ran_stat,ran_stat_cpu,ran_del,ran_del_cpu"); 253 fprintf(fp, "\n"); 254 fflush(NULL); 255} 256 257int 258BonTimer::DoReport(CPCCHAR machine, int file_size, int directory_size 259 , int max_size, int min_size, int num_directories 260 , int chunk_size, FILE *fp) 261{ 262 m_fp = fp; 263 m_file_size = file_size; 264 m_directory_size = directory_size; 265 m_chunk_size = chunk_size; 266 const int txt_machine_size = 20; 267 if(m_file_size) 268 { 269 if(m_type == txt) 270 { 271 fprintf(m_fp, "Version %5s ", BON_VERSION); 272 fprintf(m_fp, 273 "------Sequential Output------ --Sequential Input- --Random-\n"); 274 fprintf(m_fp, " "); 275 fprintf(m_fp, 276 "-Per Chr- --Block-- -Rewrite- -Per Chr- --Block-- --Seeks--\n"); 277 if(m_chunk_size == DefaultChunkSize) 278 fprintf(m_fp, "Machine Size "); 279 else 280 fprintf(m_fp, "Machine Size:chnk "); 281 fprintf(m_fp, "K/sec %%CP K/sec %%CP K/sec %%CP K/sec %%CP K/sec "); 282 fprintf(m_fp, "%%CP /sec %%CP\n"); 283 } 284 char size_buf[1024]; 285 if(m_file_size % 1024 == 0) 286 sprintf(size_buf, "%dG", m_file_size / 1024); 287 else 288 sprintf(size_buf, "%dM", m_file_size); 289 if(m_chunk_size != DefaultChunkSize) 290 { 291 char *tmp = size_buf + strlen(size_buf); 292 if(m_chunk_size >= 1024) 293 sprintf(tmp, ":%dk", m_chunk_size / 1024); 294 else 295 sprintf(tmp, ":%d", m_chunk_size); 296 } 297 char buf[4096]; 298 if(m_type == txt) 299 { 300 // copy machine name to buf 301 // 302 snprintf(buf 303#ifndef NO_SNPRINTF 304 , txt_machine_size - 1 305#endif 306 , "%s ", machine); 307 buf[txt_machine_size - 1] = '\0'; 308 // set cur to point to a byte past where we end the machine name 309 // size of the buf - size of the new data - 1 for the space - 1 for the 310 // terminating zero on the string 311 char *cur = &buf[txt_machine_size - strlen(size_buf) - 2]; 312 *cur = ' '; // make cur a space 313 cur++; // increment to where we store the size 314 strcpy(cur, size_buf); // copy the size in 315 fputs(buf, m_fp); 316 } 317 else 318 { 319 printf("%s,%s", machine, size_buf); 320 } 321 print_stat(Putc); 322 print_stat(FastWrite); 323 print_stat(ReWrite); 324 print_stat(Getc); 325 print_stat(FastRead); 326 print_stat(Lseek); 327 if(m_type == txt) 328 fprintf(m_fp, "\n"); 329 } 330 else if(m_type == csv) 331 { 332 fprintf(m_fp, "%s,,,,,,,,,,,,,", machine); 333 } 334 335 if(m_directory_size) 336 { 337 char buf[128]; 338 char *tmp; 339 sprintf(buf, "%d", m_directory_size); 340 if(max_size == -1) 341 { 342 strcat(buf, ":link"); 343 } 344 else if(max_size == -2) 345 { 346 strcat(buf, ":symlink"); 347 } 348 else if(max_size) 349 { 350 tmp = &buf[strlen(buf)]; 351 sprintf(tmp, ":%d:%d", max_size, min_size); 352 } 353 if(num_directories > 1) 354 { 355 tmp = &buf[strlen(buf)]; 356 sprintf(tmp, "/%d", num_directories); 357 } 358 if(m_type == txt) 359 { 360 if(m_file_size) 361 fprintf(m_fp, " "); 362 else 363 fprintf(m_fp, "Version %5s ", BON_VERSION); 364 fprintf(m_fp, 365 "------Sequential Create------ --------Random Create--------\n"); 366 if(m_file_size) 367 fprintf(m_fp, " "); 368 else 369 fprintf(m_fp, "%-19.19s ", machine); 370 fprintf(m_fp, 371 "-Create-- --Read--- -Delete-- -Create-- --Read--- -Delete--\n"); 372 if(min_size) 373 { 374 fprintf(m_fp, "files:max:min "); 375 } 376 else 377 { 378 if(max_size) 379 fprintf(m_fp, "files:max "); 380 else 381 fprintf(m_fp, " files "); 382 } 383 fprintf(m_fp, " /sec %%CP /sec %%CP /sec %%CP /sec %%CP /sec "); 384 fprintf(m_fp, "%%CP /sec %%CP\n"); 385 fprintf(m_fp, "%19s", buf); 386 } 387 else 388 { 389 fprintf(m_fp, ",%s", buf); 390 } 391 print_file_stat(CreateSeq); 392 print_file_stat(StatSeq); 393 print_file_stat(DelSeq); 394 print_file_stat(CreateRand); 395 print_file_stat(StatRand); 396 print_file_stat(DelRand); 397 fprintf(m_fp, "\n"); 398 } 399 else if(m_type == csv) 400 { 401 fprintf(m_fp, ",,,,,,,,,,,,,\n"); 402 } 403 fflush(stdout); 404 return 0; 405} 406 407