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