00001 #include "ace_pch.h"
00002
00003
00004 #include "ace/Stats.h"
00005 #include "ace/High_Res_Timer.h"
00006
00007 #if !defined (__ACE_INLINE__)
00008 # include "ace/Stats.i"
00009 #endif
00010
00011 ACE_RCSID(ace, Stats, "$Id: Stats.cpp,v 1.1.1.3.40.1 2003/03/13 19:44:22 chad Exp $")
00012
00013 ACE_UINT32
00014 ACE_Stats_Value::fractional_field (void) const
00015 {
00016 if (precision () == 0)
00017 {
00018 return 1;
00019 }
00020 else
00021 {
00022 ACE_UINT32 field = 10;
00023 for (u_int i = 0; i < precision () - 1; ++i)
00024 {
00025 field *= 10;
00026 }
00027
00028 return field;
00029 }
00030 }
00031
00032 int
00033 ACE_Stats::sample (const ACE_INT32 value)
00034 {
00035 if (samples_.enqueue_tail (value) == 0)
00036 {
00037 ++number_of_samples_;
00038 if (number_of_samples_ == 0)
00039 {
00040
00041 overflow_ = EFAULT;
00042 return -1;
00043 }
00044
00045 if (value < min_)
00046 min_ = value;
00047
00048 if (value > max_)
00049 max_ = value;
00050
00051 return 0;
00052 }
00053 else
00054 {
00055
00056
00057 overflow_ = errno;
00058 return -1;
00059 }
00060 }
00061
00062 void
00063 ACE_Stats::mean (ACE_Stats_Value &m,
00064 const ACE_UINT32 scale_factor)
00065 {
00066 if (number_of_samples_ > 0)
00067 {
00068 #if defined ACE_LACKS_LONGLONG_T
00069
00070
00071
00072 const ACE_U_LongLong ACE_STATS_INTERNAL_OFFSET (0, 8);
00073 #else
00074 const ACE_UINT64 ACE_STATS_INTERNAL_OFFSET =
00075 ACE_UINT64_LITERAL (0x100000000);
00076 #endif
00077
00078 ACE_UINT64 sum = ACE_STATS_INTERNAL_OFFSET;
00079 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00080 while (! i.done ())
00081 {
00082 ACE_INT32 *sample;
00083 if (i.next (sample))
00084 {
00085 sum += *sample;
00086 i.advance ();
00087 }
00088 }
00089
00090
00091
00092 quotient (sum - ACE_STATS_INTERNAL_OFFSET,
00093 number_of_samples_ * scale_factor,
00094 m);
00095 }
00096 else
00097 {
00098 m.whole (0);
00099 m.fractional (0);
00100 }
00101 }
00102
00103 int
00104 ACE_Stats::std_dev (ACE_Stats_Value &std_dev,
00105 const ACE_UINT32 scale_factor)
00106 {
00107 if (number_of_samples_ <= 1)
00108 {
00109 std_dev.whole (0);
00110 std_dev.fractional (0);
00111 }
00112 else
00113 {
00114 const ACE_UINT32 field = std_dev.fractional_field ();
00115
00116
00117
00118
00119
00120 ACE_UINT64 mean_scaled;
00121
00122
00123 ACE_Stats_Value avg (std_dev.precision ());
00124 mean (avg, 1u);
00125 avg.scaled_value (mean_scaled);
00126
00127
00128
00129 ACE_UINT64 sum_of_squares = 0;
00130 ACE_Unbounded_Queue_Iterator<ACE_INT32> i (samples_);
00131 while (! i.done ())
00132 {
00133 ACE_INT32 *sample;
00134 if (i.next (sample))
00135 {
00136 const ACE_UINT64 original_sum_of_squares = sum_of_squares;
00137
00138
00139
00140 const ACE_UINT64 product (*sample * field);
00141
00142 ACE_UINT64 difference;
00143
00144
00145 if (product >= mean_scaled)
00146 {
00147 difference = product - mean_scaled;
00148 }
00149 else
00150 {
00151 difference = mean_scaled - product;
00152 }
00153
00154
00155
00156
00157 sum_of_squares += difference * ACE_U64_TO_U32 (difference);
00158 i.advance ();
00159
00160 if (sum_of_squares < original_sum_of_squares)
00161 {
00162 overflow_ = ENOSPC;
00163 return -1;
00164 }
00165 }
00166 }
00167
00168
00169
00170
00171 ACE_Stats_Value variance (std_dev.precision ());
00172 quotient (sum_of_squares,
00173 (number_of_samples_ - 1) * field * field,
00174 variance);
00175
00176
00177
00178 ACE_UINT64 scaled_variance;
00179 variance.scaled_value (scaled_variance);
00180
00181
00182
00183 scaled_variance *= field;
00184 ACE_Stats_Value unscaled_standard_deviation (std_dev.precision ());
00185 square_root (scaled_variance,
00186 unscaled_standard_deviation);
00187
00188
00189 quotient (unscaled_standard_deviation,
00190 scale_factor * field,
00191 std_dev);
00192 }
00193
00194 return 0;
00195 }
00196
00197
00198 void
00199 ACE_Stats::reset (void)
00200 {
00201 overflow_ = 0u;
00202 number_of_samples_ = 0u;
00203 min_ = 0x7FFFFFFF;
00204 max_ = -0x8000 * 0x10000;
00205 samples_.reset ();
00206 }
00207
00208 int
00209 ACE_Stats::print_summary (const u_int precision,
00210 const ACE_UINT32 scale_factor,
00211 FILE *file) const
00212 {
00213 ACE_TCHAR mean_string [128];
00214 ACE_TCHAR std_dev_string [128];
00215 ACE_TCHAR min_string [128];
00216 ACE_TCHAR max_string [128];
00217 int success = 0;
00218
00219 for (int tmp_precision = precision;
00220 ! overflow_ && ! success && tmp_precision >= 0;
00221 --tmp_precision)
00222 {
00223
00224 ACE_TCHAR format[32];
00225 if (tmp_precision == 0)
00226 ACE_OS::sprintf (format, ACE_LIB_TEXT ("%%%d"), tmp_precision);
00227 else
00228 ACE_OS::sprintf (format, ACE_LIB_TEXT ("%%d.%%0%du"), tmp_precision);
00229
00230 ACE_Stats_Value u (tmp_precision);
00231 ((ACE_Stats *) this)->mean (u, scale_factor);
00232 ACE_OS::sprintf (mean_string, format, u.whole (), u.fractional ());
00233
00234 ACE_Stats_Value sd (tmp_precision);
00235 if (((ACE_Stats *) this)->std_dev (sd, scale_factor))
00236 {
00237 success = 0;
00238 continue;
00239 }
00240 else
00241 {
00242 success = 1;
00243 }
00244 ACE_OS::sprintf (std_dev_string, format, sd.whole (), sd.fractional ());
00245
00246 ACE_Stats_Value minimum (tmp_precision), maximum (tmp_precision);
00247 if (min_ != 0)
00248 {
00249 const ACE_UINT64 m (min_);
00250 quotient (m, scale_factor, minimum);
00251 }
00252 if (max_ != 0)
00253 {
00254 const ACE_UINT64 m (max_);
00255 quotient (m, scale_factor, maximum);
00256 }
00257 ACE_OS::sprintf (min_string, format,
00258 minimum.whole (), minimum.fractional ());
00259 ACE_OS::sprintf (max_string, format,
00260 maximum.whole (), maximum.fractional ());
00261 }
00262
00263 if (success == 1)
00264 {
00265 ACE_OS::fprintf (file, ACE_LIB_TEXT ("samples: %u (%s - %s); mean: ")
00266 ACE_LIB_TEXT ("%s; std dev: %s\n"),
00267 samples (), min_string, max_string,
00268 mean_string, std_dev_string);
00269 return 0;
00270 }
00271 else
00272 {
00273 #if !defined (ACE_HAS_WINCE)
00274 ACE_OS::fprintf (file,
00275 ACE_LIB_TEXT ("ACE_Stats::print_summary: OVERFLOW: %s\n"),
00276 strerror (overflow_));
00277 #else
00278
00279 ACE_OS::fprintf (file,
00280 ACE_LIB_TEXT ("ACE_Stats::print_summary: OVERFLOW\n"));
00281 #endif
00282 return -1;
00283 }
00284 }
00285
00286 void
00287 ACE_Stats::quotient (const ACE_UINT64 dividend,
00288 const ACE_UINT32 divisor,
00289 ACE_Stats_Value "ient)
00290 {
00291
00292 quotient.whole (ACE_static_cast (ACE_UINT32,
00293 divisor == 0 ? 0 : dividend / divisor));
00294
00295 if (quotient.precision () > 0 || divisor == 0)
00296 {
00297 const ACE_UINT32 field = quotient.fractional_field ();
00298
00299
00300
00301
00302
00303
00304
00305
00306 quotient.fractional (ACE_static_cast (ACE_UINT32,
00307 dividend % divisor * field / divisor));
00308 }
00309 else
00310 {
00311
00312
00313 quotient.fractional (0);
00314 }
00315 }
00316
00317 void
00318 ACE_Stats::quotient (const ACE_Stats_Value ÷nd,
00319 const ACE_UINT32 divisor,
00320 ACE_Stats_Value "ient)
00321 {
00322
00323 quotient.whole (divisor == 0 ? 0 : dividend.whole () / divisor);
00324
00325 if (quotient.precision () > 0 || divisor == 0)
00326 {
00327 const ACE_UINT32 field = quotient.fractional_field ();
00328
00329
00330 quotient.fractional (dividend.whole () % divisor * field / divisor +
00331 dividend.fractional () / divisor);
00332 }
00333 else
00334 {
00335
00336
00337 quotient.fractional (0);
00338 }
00339 }
00340
00341 void
00342 ACE_Stats::square_root (const ACE_UINT64 n,
00343 ACE_Stats_Value &square_root)
00344 {
00345 ACE_UINT32 floor = 0;
00346 ACE_UINT32 ceiling = 0xFFFFFFFFu;
00347 ACE_UINT32 mid = 0;
00348 u_int i;
00349
00350
00351 for (i = 0; i < 64; ++i)
00352 {
00353 mid = (ceiling - floor) / 2 + floor;
00354 if (floor == mid)
00355
00356 break;
00357 else
00358 {
00359
00360 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00361 if (mid_squared == n)
00362 break;
00363 else if (mid_squared < n)
00364 floor = mid;
00365 else
00366 ceiling = mid;
00367 }
00368 }
00369
00370 square_root.whole (mid);
00371 ACE_UINT64 mid_squared = mid; mid_squared *= mid;
00372
00373 if (square_root.precision () && mid_squared < n)
00374 {
00375
00376
00377
00378 const ACE_UINT32 field = square_root.fractional_field ();
00379
00380 floor = 0;
00381 ceiling = field;
00382 mid = 0;
00383
00384
00385 ACE_UINT64 target = n;
00386 target *= field;
00387 target *= field;
00388
00389 ACE_UINT64 difference = 0;
00390
00391 for (i = 0; i < square_root.precision (); ++i)
00392 {
00393 mid = (ceiling - floor) / 2 + floor;
00394
00395 ACE_UINT64 current = square_root.whole () * field + mid;
00396 current *= square_root.whole () * field + mid;
00397
00398 if (floor == mid)
00399 {
00400 difference = target - current;
00401 break;
00402 }
00403 else if (current <= target)
00404 floor = mid;
00405 else
00406 ceiling = mid;
00407 }
00408
00409
00410 ACE_UINT64 next = square_root.whole () * field + mid + 1;
00411 next *= square_root.whole () * field + mid + 1;
00412
00413 square_root.fractional (next - target < difference ? mid + 1 : mid);
00414 }
00415 else
00416 {
00417
00418
00419 square_root.fractional (0);
00420 }
00421 }
00422
00423
00424
00425 ACE_Throughput_Stats::ACE_Throughput_Stats (void)
00426 : ACE_Basic_Stats ()
00427 , throughput_last_ (0)
00428 #if 0
00429
00430
00431 , throughput_sum_x_ (0)
00432 , throughput_sum_x2_ (0)
00433 , throughput_sum_y_ (0)
00434 , throughput_sum_y2_ (0)
00435 , throughput_sum_xy_ (0)
00436 #endif
00437 {
00438 }
00439
00440 void
00441 ACE_Throughput_Stats::sample (ACE_UINT64 throughput,
00442 ACE_UINT64 latency)
00443 {
00444 this->ACE_Basic_Stats::sample (latency);
00445
00446 if (this->samples_count () == 1u)
00447 {
00448
00449 this->throughput_last_ = throughput;
00450 #if 0
00451
00452
00453 this->throughput_sum_y_ = this->samples_count_;
00454 this->throughput_sum_y2_ = this->samples_count_ * this->samples_count_;
00455 this->throughput_sum_x_ = throughput;
00456 this->throughput_sum_x2_ = throughput * throughput;
00457 this->throughput_sum_xy_ = throughput * this->samples_count_;
00458
00459 printf ("%f %qu\n", throughput / 400000000.0, this->samples_count_);
00460 #endif
00461 }
00462 else
00463 {
00464 this->throughput_last_ = throughput;
00465
00466 #if 0
00467
00468
00469 this->throughput_sum_y_ += this->samples_count_;
00470 this->throughput_sum_y2_ += this->samples_count_ * this->samples_count_;
00471 this->throughput_sum_x_ += throughput;
00472 this->throughput_sum_x2_ += throughput * throughput;
00473 this->throughput_sum_xy_ += throughput * this->samples_count_;
00474
00475 printf ("%f %qu\n", throughput / 400000000.0, this->samples_count_);
00476 #endif
00477 }
00478 }
00479
00480 void
00481 ACE_Throughput_Stats::accumulate (const ACE_Throughput_Stats &rhs)
00482 {
00483 if (rhs.samples_count () == 0u)
00484 return;
00485
00486 this->ACE_Basic_Stats::accumulate (rhs);
00487
00488 if (this->samples_count () == 0u)
00489 {
00490 this->throughput_last_ = rhs.throughput_last_;
00491 #if 0
00492
00493
00494 this->throughput_sum_x_ = rhs.throughput_sum_x_;
00495 this->throughput_sum_x2_ = rhs.throughput_sum_x2_;
00496 this->throughput_sum_y_ = rhs.throughput_sum_y_;
00497 this->throughput_sum_y2_ = rhs.throughput_sum_y2_;
00498 this->throughput_sum_xy_ = rhs.throughput_sum_xy_;
00499 #endif
00500
00501 return;
00502 }
00503
00504
00505 if (this->throughput_last_ < rhs.throughput_last_)
00506 this->throughput_last_ = rhs.throughput_last_;
00507
00508 #if 0
00509
00510
00511 this->throughput_sum_x_ += rhs.throughput_sum_x_;
00512 this->throughput_sum_x2_ += rhs.throughput_sum_x2_;
00513 this->throughput_sum_y_ += rhs.throughput_sum_y_;
00514 this->throughput_sum_y2_ += rhs.throughput_sum_y2_;
00515 this->throughput_sum_xy_ += rhs.throughput_sum_xy_;
00516 #endif
00517 }
00518
00519 void
00520 ACE_Throughput_Stats::dump_results (const ACE_TCHAR* msg,
00521 ACE_UINT32 sf)
00522 {
00523 if (this->samples_count () == 0u)
00524 {
00525 ACE_DEBUG ((LM_DEBUG,
00526 ACE_LIB_TEXT ("%s : no data collected\n"), msg));
00527 return;
00528 }
00529
00530 this->ACE_Basic_Stats::dump_results (msg, sf);
00531
00532 ACE_Throughput_Stats::dump_throughput (msg, sf,
00533 this->throughput_last_,
00534 this->samples_count ());
00535
00536 #if 0
00537
00538
00539 double t_sum_x =
00540 ACE_CU64_TO_CU32 (this->throughput_sum_x_);
00541
00542 double t_sum_y =
00543 ACE_CU64_TO_CU32 (this->throughput_sum_y_);
00544 double t_sum_x2 =
00545 ACE_CU64_TO_CU32 (this->throughput_sum_x2_);
00546
00547
00548 double t_sum_y2 =
00549 ACE_CU64_TO_CU32 (this->throughput_sum_y2_);
00550 double t_sum_xy =
00551 ACE_CU64_TO_CU32 (this->throughput_sum_xy_);
00552
00553 double t_avgx = t_sum_x / this->samples_count ();
00554 double t_avgy = t_sum_y / this->samples_count ();
00555
00556 double t_a =
00557 (this->samples_count () * t_sum_xy - t_sum_x * t_sum_y)
00558 / (this->samples_count () * t_sum_x2 - t_sum_x * t_sum_x);
00559 double t_b = (t_avgy - t_a * t_avgx);
00560
00561 t_a *= 1000000.0;
00562
00563 double d_r =
00564 (t_sum_xy - t_avgx * t_sum_y - t_avgy * t_sum_x
00565 + this->samples_count () * t_avgx * t_avgy);
00566 double n_r =
00567 (t_sum_x2
00568 - this->samples_count () * t_avgx * t_avgx)
00569 * (t_sum_y2
00570 - this->samples_count () * t_avgy * t_avgy);
00571 double t_r = d_r * d_r / n_r;
00572
00573
00574
00575
00576
00577
00578
00579 #endif
00580 }
00581
00582 void
00583 ACE_Throughput_Stats::dump_throughput (const ACE_TCHAR *msg,
00584 ACE_UINT32 sf,
00585 ACE_UINT64 elapsed_time,
00586 ACE_UINT32 samples_count)
00587 {
00588 double seconds =
00589 #if defined ACE_LACKS_LONGLONG_T
00590 elapsed_time / sf;
00591 #else
00592 ACE_static_cast (double,
00593 ACE_UINT64_DBLCAST_ADAPTER(elapsed_time / sf));
00594 #endif
00595 seconds /= ACE_HR_SCALE_CONVERSION;
00596 double t_avg = samples_count / seconds;
00597
00598 ACE_DEBUG ((LM_DEBUG,
00599 ACE_LIB_TEXT ("%s throughput: %.2f (events/second)\n"),
00600 msg, t_avg));
00601 }
00602
00603
00604
00605 #if defined (ACE_HAS_EXPLICIT_TEMPLATE_INSTANTIATION)
00606 template class ACE_Node <ACE_INT32>;
00607 template class ACE_Unbounded_Queue <ACE_INT32>;
00608 template class ACE_Unbounded_Queue_Iterator <ACE_INT32>;
00609 #elif defined (ACE_HAS_TEMPLATE_INSTANTIATION_PRAGMA)
00610 #pragma instantiate ACE_Node <ACE_INT32>
00611 #pragma instantiate ACE_Unbounded_Queue <ACE_INT32>
00612 #pragma instantiate ACE_Unbounded_Queue_Iterator <ACE_INT32>
00613 #endif