Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2008, Google Inc.
      2 // All rights reserved.
      3 //
      4 // Redistribution and use in source and binary forms, with or without
      5 // modification, are permitted provided that the following conditions are
      6 // met:
      7 //
      8 //     * Redistributions of source code must retain the above copyright
      9 // notice, this list of conditions and the following disclaimer.
     10 //     * Redistributions in binary form must reproduce the above
     11 // copyright notice, this list of conditions and the following disclaimer
     12 // in the documentation and/or other materials provided with the
     13 // distribution.
     14 //     * Neither the name of Google Inc. nor the names of its
     15 // contributors may be used to endorse or promote products derived from
     16 // this software without specific prior written permission.
     17 //
     18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29 
     30 // ---
     31 // All Rights Reserved.
     32 //
     33 // Author: Daniel Ford
     34 //
     35 // Checks basic properties of the sampler
     36 
     37 #include "config_for_unittests.h"
     38 #include <stdlib.h>        // defines posix_memalign
     39 #include <stdio.h>         // for the printf at the end
     40 #if defined HAVE_STDINT_H
     41 #include <stdint.h>             // to get uintptr_t
     42 #elif defined HAVE_INTTYPES_H
     43 #include <inttypes.h>           // another place uintptr_t might be defined
     44 #endif
     45 #include <sys/types.h>
     46 #include <iostream>
     47 #include <algorithm>
     48 #include <vector>
     49 #include <string>
     50 #include <cmath>
     51 #include "base/logging.h"
     52 #include "base/commandlineflags.h"
     53 #include "sampler.h"       // The Sampler class being tested
     54 
     55 using std::sort;
     56 using std::min;
     57 using std::max;
     58 using std::vector;
     59 using std::abs;
     60 
     61 vector<void (*)()> g_testlist;  // the tests to run
     62 
     63 #define TEST(a, b)                                      \
     64   struct Test_##a##_##b {                               \
     65     Test_##a##_##b() { g_testlist.push_back(&Run); }    \
     66     static void Run();                                  \
     67   };                                                    \
     68   static Test_##a##_##b g_test_##a##_##b;               \
     69   void Test_##a##_##b::Run()
     70 
     71 
     72 static int RUN_ALL_TESTS() {
     73   vector<void (*)()>::const_iterator it;
     74   for (it = g_testlist.begin(); it != g_testlist.end(); ++it) {
     75     (*it)();   // The test will error-exit if there's a problem.
     76   }
     77   fprintf(stderr, "\nPassed %d tests\n\nPASS\n", (int)g_testlist.size());
     78   return 0;
     79 }
     80 
     81 #undef LOG   // defined in base/logging.h
     82 // Ideally, we'd put the newline at the end, but this hack puts the
     83 // newline at the end of the previous log message, which is good enough :-)
     84 #define LOG(level)  std::cerr << "\n"
     85 
     86 static std::string StringPrintf(const char* format, ...) {
     87   char buf[256];   // should be big enough for all logging
     88   va_list ap;
     89   va_start(ap, format);
     90   perftools_vsnprintf(buf, sizeof(buf), format, ap);
     91   va_end(ap);
     92   return buf;
     93 }
     94 
     95 namespace {
     96 template<typename T> class scoped_array {
     97  public:
     98   scoped_array(T* p) : p_(p) { }
     99   ~scoped_array() { delete[] p_; }
    100   const T* get() const { return p_; }
    101   T* get() { return p_; }
    102   T& operator[](int i) { return p_[i]; }
    103  private:
    104   T* p_;
    105 };
    106 }
    107 
    108 // Note that these tests are stochastic.
    109 // This mean that the chance of correct code passing the test is,
    110 // in the case of 5 standard deviations:
    111 // kSigmas=5:    ~99.99994267%
    112 // in the case of 4 standard deviations:
    113 // kSigmas=4:    ~99.993666%
    114 static const double kSigmas = 4;
    115 static const size_t kSamplingInterval = 512*1024;
    116 
    117 // Tests that GetSamplePeriod returns the expected value
    118 // which is 1<<19
    119 TEST(Sampler, TestGetSamplePeriod) {
    120   tcmalloc::Sampler sampler;
    121   sampler.Init(1);
    122   uint64_t sample_period;
    123   sample_period = sampler.GetSamplePeriod();
    124   CHECK_GT(sample_period, 0);
    125 }
    126 
    127 // Tests of the quality of the random numbers generated
    128 // This uses the Anderson Darling test for uniformity.
    129 // See "Evaluating the Anderson-Darling Distribution" by Marsaglia
    130 // for details.
    131 
    132 // Short cut version of ADinf(z), z>0 (from Marsaglia)
    133 // This returns the p-value for Anderson Darling statistic in
    134 // the limit as n-> infinity. For finite n, apply the error fix below.
    135 double AndersonDarlingInf(double z) {
    136   if (z < 2) {
    137     return exp(-1.2337141 / z) / sqrt(z) * (2.00012 + (0.247105 -
    138                 (0.0649821 - (0.0347962 - (0.011672 - 0.00168691
    139                 * z) * z) * z) * z) * z);
    140   }
    141   return exp( - exp(1.0776 - (2.30695 - (0.43424 - (0.082433 -
    142                     (0.008056 - 0.0003146 * z) * z) * z) * z) * z));
    143 }
    144 
    145 // Corrects the approximation error in AndersonDarlingInf for small values of n
    146 // Add this to AndersonDarlingInf to get a better approximation
    147 // (from Marsaglia)
    148 double AndersonDarlingErrFix(int n, double x) {
    149   if (x > 0.8) {
    150     return (-130.2137 + (745.2337 - (1705.091 - (1950.646 -
    151             (1116.360 - 255.7844 * x) * x) * x) * x) * x) / n;
    152   }
    153   double cutoff = 0.01265 + 0.1757 / n;
    154   double t;
    155   if (x < cutoff) {
    156     t = x / cutoff;
    157     t = sqrt(t) * (1 - t) * (49 * t - 102);
    158     return t * (0.0037 / (n * n) + 0.00078 / n + 0.00006) / n;
    159   } else {
    160     t = (x - cutoff) / (0.8 - cutoff);
    161     t = -0.00022633 + (6.54034 - (14.6538 - (14.458 - (8.259 - 1.91864
    162           * t) * t) * t) * t) * t;
    163     return t * (0.04213 + 0.01365 / n) / n;
    164   }
    165 }
    166 
    167 // Returns the AndersonDarling p-value given n and the value of the statistic
    168 double AndersonDarlingPValue(int n, double z) {
    169   double ad = AndersonDarlingInf(z);
    170   double errfix = AndersonDarlingErrFix(n, ad);
    171   return ad + errfix;
    172 }
    173 
    174 double AndersonDarlingStatistic(int n, double* random_sample) {
    175   double ad_sum = 0;
    176   for (int i = 0; i < n; i++) {
    177     ad_sum += (2*i + 1) * log(random_sample[i] * (1 - random_sample[n-1-i]));
    178   }
    179   double ad_statistic = - n - 1/static_cast<double>(n) * ad_sum;
    180   return ad_statistic;
    181 }
    182 
    183 // Tests if the array of doubles is uniformly distributed.
    184 // Returns the p-value of the Anderson Darling Statistic
    185 // for the given set of sorted random doubles
    186 // See "Evaluating the Anderson-Darling Distribution" by
    187 // Marsaglia and Marsaglia for details.
    188 double AndersonDarlingTest(int n, double* random_sample) {
    189   double ad_statistic = AndersonDarlingStatistic(n, random_sample);
    190   LOG(INFO) << StringPrintf("AD stat = %f, n=%d\n", ad_statistic, n);
    191   double p = AndersonDarlingPValue(n, ad_statistic);
    192   return p;
    193 }
    194 
    195 // Test the AD Test. The value of the statistic should go to zero as n->infty
    196 // Not run as part of regular tests
    197 void ADTestTest(int n) {
    198   scoped_array<double> random_sample(new double[n]);
    199   for (int i = 0; i < n; i++) {
    200     random_sample[i] = (i+0.01)/n;
    201   }
    202   sort(random_sample.get(), random_sample.get() + n);
    203   double ad_stat = AndersonDarlingStatistic(n, random_sample.get());
    204   LOG(INFO) << StringPrintf("Testing the AD test. n=%d, ad_stat = %f",
    205                             n, ad_stat);
    206 }
    207 
    208 // Print the CDF of the distribution of the Anderson-Darling Statistic
    209 // Used for checking the Anderson-Darling Test
    210 // Not run as part of regular tests
    211 void ADCDF() {
    212   for (int i = 1; i < 40; i++) {
    213     double x = i/10.0;
    214     LOG(INFO) << "x= " << x << "  adpv= "
    215               << AndersonDarlingPValue(100, x) << ", "
    216               << AndersonDarlingPValue(1000, x);
    217   }
    218 }
    219 
    220 // Testing that NextRandom generates uniform
    221 // random numbers.
    222 // Applies the Anderson-Darling test for uniformity
    223 void TestNextRandom(int n) {
    224   tcmalloc::Sampler sampler;
    225   sampler.Init(1);
    226   uint64_t x = 1;
    227   // This assumes that the prng returns 48 bit numbers
    228   uint64_t max_prng_value = static_cast<uint64_t>(1)<<48;
    229   // Initialize
    230   for (int i = 1; i <= 20; i++) {  // 20 mimics sampler.Init()
    231     x = sampler.NextRandom(x);
    232   }
    233   scoped_array<uint64_t> int_random_sample(new uint64_t[n]);
    234   // Collect samples
    235   for (int i = 0; i < n; i++) {
    236     int_random_sample[i] = x;
    237     x = sampler.NextRandom(x);
    238   }
    239   // First sort them...
    240   sort(int_random_sample.get(), int_random_sample.get() + n);
    241   scoped_array<double> random_sample(new double[n]);
    242   // Convert them to uniform randoms (in the range [0,1])
    243   for (int i = 0; i < n; i++) {
    244     random_sample[i] = static_cast<double>(int_random_sample[i])/max_prng_value;
    245   }
    246   // Now compute the Anderson-Darling statistic
    247   double ad_pvalue = AndersonDarlingTest(n, random_sample.get());
    248   LOG(INFO) << StringPrintf("pvalue for AndersonDarlingTest "
    249                             "with n= %d is p= %f\n", n, ad_pvalue);
    250   CHECK_GT(min(ad_pvalue, 1 - ad_pvalue), 0.0001);
    251   //           << StringPrintf("prng is not uniform, %d\n", n);
    252 }
    253 
    254 
    255 TEST(Sampler, TestNextRandom_MultipleValues) {
    256   TestNextRandom(10);  // Check short-range correlation
    257   TestNextRandom(100);
    258   TestNextRandom(1000);
    259   TestNextRandom(10000);  // Make sure there's no systematic error
    260 }
    261 
    262 // Tests that PickNextSamplePeriod generates
    263 // geometrically distributed random numbers.
    264 // First converts to uniforms then applied the
    265 // Anderson-Darling test for uniformity.
    266 void TestPickNextSample(int n) {
    267   tcmalloc::Sampler sampler;
    268   sampler.Init(1);
    269   scoped_array<uint64_t> int_random_sample(new uint64_t[n]);
    270   int sample_period = sampler.GetSamplePeriod();
    271   int ones_count = 0;
    272   for (int i = 0; i < n; i++) {
    273     int_random_sample[i] = sampler.PickNextSamplingPoint();
    274     CHECK_GE(int_random_sample[i], 1);
    275     if (int_random_sample[i] == 1) {
    276       ones_count += 1;
    277     }
    278     CHECK_LT(ones_count, 4); // << " out of " << i << " samples.";
    279   }
    280   // First sort them...
    281   sort(int_random_sample.get(), int_random_sample.get() + n);
    282   scoped_array<double> random_sample(new double[n]);
    283   // Convert them to uniform random numbers
    284   // by applying the geometric CDF
    285   for (int i = 0; i < n; i++) {
    286     random_sample[i] = 1 - exp(-static_cast<double>(int_random_sample[i])
    287                            / sample_period);
    288   }
    289   // Now compute the Anderson-Darling statistic
    290   double geom_ad_pvalue = AndersonDarlingTest(n, random_sample.get());
    291   LOG(INFO) << StringPrintf("pvalue for geometric AndersonDarlingTest "
    292                              "with n= %d is p= %f\n", n, geom_ad_pvalue);
    293   CHECK_GT(min(geom_ad_pvalue, 1 - geom_ad_pvalue), 0.0001);
    294       //          << "PickNextSamplingPoint does not produce good "
    295       //             "geometric/exponential random numbers\n";
    296 }
    297 
    298 TEST(Sampler, TestPickNextSample_MultipleValues) {
    299   TestPickNextSample(10);  // Make sure the first few are good (enough)
    300   TestPickNextSample(100);
    301   TestPickNextSample(1000);
    302   TestPickNextSample(10000);  // Make sure there's no systematic error
    303 }
    304 
    305 
    306 // This is superceeded by the Anderson-Darling Test
    307 // and it not run now.
    308 // Tests how fast nearby values are spread out with  LRand64
    309 // The purpose of this code is to determine how many
    310 // steps to apply to the seed during initialization
    311 void TestLRand64Spread() {
    312   tcmalloc::Sampler sampler;
    313   sampler.Init(1);
    314   uint64_t current_value;
    315   printf("Testing LRand64 Spread\n");
    316   for (int i = 1; i < 10; i++) {
    317     printf("%d ", i);
    318     current_value = i;
    319     for (int j = 1; j < 100; j++) {
    320       current_value = sampler.NextRandom(current_value);
    321     }
    322     LOG(INFO) << current_value;
    323   }
    324 }
    325 
    326 
    327 // Test for Fastlog2 code
    328 // We care about the percentage error because we're using this
    329 // for choosing step sizes, so "close" is relative to the size of
    330 // the step we would get if we used the built-in log function
    331 TEST(Sampler, FastLog2) {
    332   tcmalloc::Sampler sampler;
    333   sampler.Init(1);
    334   double max_ratio_error = 0;
    335   for (double d = -1021.9; d < 1; d+= 0.13124235) {
    336     double e = pow(2.0, d);
    337     double truelog = log(e) / log(2.0);  // log_2(e)
    338     double fastlog = sampler.FastLog2(e);
    339     max_ratio_error = max(max_ratio_error,
    340                           max(truelog/fastlog-1, fastlog/truelog-1));
    341     CHECK_LE(max_ratio_error, 0.01);
    342         //        << StringPrintf("d = %f, e=%f, truelog = %f, fastlog= %f\n",
    343         //                        d, e, truelog, fastlog);
    344   }
    345   LOG(INFO) << StringPrintf("Fastlog2: max_ratio_error = %f\n",
    346                             max_ratio_error);
    347 }
    348 
    349 // Futher tests
    350 
    351 bool CheckMean(size_t mean, int num_samples) {
    352   tcmalloc::Sampler sampler;
    353   sampler.Init(1);
    354   size_t total = 0;
    355   for (int i = 0; i < num_samples; i++) {
    356     total += sampler.PickNextSamplingPoint();
    357   }
    358   double empirical_mean = total / static_cast<double>(num_samples);
    359   double expected_sd = mean / pow(num_samples * 1.0, 0.5);
    360   return(fabs(mean-empirical_mean) < expected_sd * kSigmas);
    361 }
    362 
    363 // Prints a sequence so you can look at the distribution
    364 void OutputSequence(int sequence_length) {
    365   tcmalloc::Sampler sampler;
    366   sampler.Init(1);
    367   size_t next_step;
    368   for (int i = 0; i< sequence_length; i++) {
    369     next_step = sampler.PickNextSamplingPoint();
    370     LOG(INFO) << next_step;
    371   }
    372 }
    373 
    374 
    375 double StandardDeviationsErrorInSample(
    376               int total_samples, int picked_samples,
    377               int alloc_size, int sampling_interval) {
    378   double p = 1 - exp(-(static_cast<double>(alloc_size) / sampling_interval));
    379   double expected_samples = total_samples * p;
    380   double sd = pow(p*(1-p)*total_samples, 0.5);
    381   return((picked_samples - expected_samples) / sd);
    382 }
    383 
    384 TEST(Sampler, LargeAndSmallAllocs_CombinedTest) {
    385   tcmalloc::Sampler sampler;
    386   sampler.Init(1);
    387   int counter_big = 0;
    388   int counter_small = 0;
    389   int size_big = 129*8*1024+1;
    390   int size_small = 1024*8;
    391   int num_iters = 128*4*8;
    392   // Allocate in mixed chunks
    393   for (int i = 0; i < num_iters; i++) {
    394     if (sampler.SampleAllocation(size_big)) {
    395       counter_big += 1;
    396     }
    397     for (int i = 0; i < 129; i++) {
    398       if (sampler.SampleAllocation(size_small)) {
    399         counter_small += 1;
    400       }
    401     }
    402   }
    403   // Now test that there are the right number of each
    404   double large_allocs_sds =
    405      StandardDeviationsErrorInSample(num_iters, counter_big,
    406                                      size_big, kSamplingInterval);
    407   double small_allocs_sds =
    408      StandardDeviationsErrorInSample(num_iters*129, counter_small,
    409                                      size_small, kSamplingInterval);
    410   LOG(INFO) << StringPrintf("large_allocs_sds = %f\n", large_allocs_sds);
    411   LOG(INFO) << StringPrintf("small_allocs_sds = %f\n", small_allocs_sds);
    412   CHECK_LE(fabs(large_allocs_sds), kSigmas);
    413   CHECK_LE(fabs(small_allocs_sds), kSigmas);
    414 }
    415 
    416 // Tests whether the mean is about right over 1000 samples
    417 TEST(Sampler, IsMeanRight) {
    418   CHECK(CheckMean(kSamplingInterval, 1000));
    419 }
    420 
    421 // This flag is for the OldSampler class to use
    422 const int64 FLAGS_mock_tcmalloc_sample_parameter = 1<<19;
    423 
    424 // A cut down and slightly refactored version of the old Sampler
    425 class OldSampler {
    426  public:
    427   void Init(uint32_t seed);
    428   void Cleanup() {}
    429 
    430   // Record allocation of "k" bytes.  Return true iff allocation
    431   // should be sampled
    432   bool SampleAllocation(size_t k);
    433 
    434   // Generate a geometric with mean 1M (or FLAG value)
    435   void PickNextSample(size_t k);
    436 
    437   // Initialize the statics for the Sample class
    438   static void InitStatics() {
    439     sample_period = 1048583;
    440   }
    441   size_t bytes_until_sample_;
    442 
    443  private:
    444   uint32_t rnd_;                   // Cheap random number generator
    445   static uint64_t sample_period;
    446   // Should be a prime just above a power of 2:
    447   // 2, 5, 11, 17, 37, 67, 131, 257,
    448   // 521, 1031, 2053, 4099, 8209, 16411,
    449   // 32771, 65537, 131101, 262147, 524309, 1048583,
    450   // 2097169, 4194319, 8388617, 16777259, 33554467
    451 };
    452 
    453 // Statics for OldSampler
    454 uint64_t OldSampler::sample_period;
    455 
    456 void OldSampler::Init(uint32_t seed) {
    457   // Initialize PRNG -- run it for a bit to get to good values
    458   if (seed != 0) {
    459     rnd_ = seed;
    460   } else {
    461     rnd_ = 12345;
    462   }
    463   bytes_until_sample_ = 0;
    464   for (int i = 0; i < 100; i++) {
    465     PickNextSample(sample_period * 2);
    466   }
    467 };
    468 
    469 // A cut-down version of the old PickNextSampleRoutine
    470 void OldSampler::PickNextSample(size_t k) {
    471   // Make next "random" number
    472   // x^32+x^22+x^2+x^1+1 is a primitive polynomial for random numbers
    473   static const uint32_t kPoly = (1 << 22) | (1 << 2) | (1 << 1) | (1 << 0);
    474   uint32_t r = rnd_;
    475   rnd_ = (r << 1) ^ ((static_cast<int32_t>(r) >> 31) & kPoly);
    476 
    477   // Next point is "rnd_ % (sample_period)".  I.e., average
    478   // increment is "sample_period/2".
    479   const int flag_value = FLAGS_mock_tcmalloc_sample_parameter;
    480   static int last_flag_value = -1;
    481 
    482   if (flag_value != last_flag_value) {
    483     // There should be a spinlock here, but this code is
    484     // for benchmarking only.
    485     sample_period = 1048583;
    486     last_flag_value = flag_value;
    487   }
    488 
    489   bytes_until_sample_ += rnd_ % sample_period;
    490 
    491   if (k > (static_cast<size_t>(-1) >> 2)) {
    492     // If the user has asked for a huge allocation then it is possible
    493     // for the code below to loop infinitely.  Just return (note that
    494     // this throws off the sampling accuracy somewhat, but a user who
    495     // is allocating more than 1G of memory at a time can live with a
    496     // minor inaccuracy in profiling of small allocations, and also
    497     // would rather not wait for the loop below to terminate).
    498     return;
    499   }
    500 
    501   while (bytes_until_sample_ < k) {
    502     // Increase bytes_until_sample_ by enough average sampling periods
    503     // (sample_period >> 1) to allow us to sample past the current
    504     // allocation.
    505     bytes_until_sample_ += (sample_period >> 1);
    506   }
    507 
    508   bytes_until_sample_ -= k;
    509 }
    510 
    511 inline bool OldSampler::SampleAllocation(size_t k) {
    512   if (bytes_until_sample_ < k) {
    513     PickNextSample(k);
    514     return true;
    515   } else {
    516     bytes_until_sample_ -= k;
    517     return false;
    518   }
    519 }
    520 
    521 // This checks that the stated maximum value for the
    522 // tcmalloc_sample_parameter flag never overflows bytes_until_sample_
    523 TEST(Sampler, bytes_until_sample_Overflow_Underflow) {
    524   tcmalloc::Sampler sampler;
    525   sampler.Init(1);
    526   uint64_t one = 1;
    527   // sample_parameter = 0;  // To test the edge case
    528   uint64_t sample_parameter_array[4] = {0, 1, one<<19, one<<58};
    529   for (int i = 0; i < 4; i++) {
    530     uint64_t sample_parameter = sample_parameter_array[i];
    531     LOG(INFO) << "sample_parameter = " << sample_parameter;
    532     double sample_scaling = - log(2.0) * sample_parameter;
    533     // Take the top 26 bits as the random number
    534     // (This plus the 1<<26 sampling bound give a max step possible of
    535     // 1209424308 bytes.)
    536     const uint64_t prng_mod_power = 48;  // Number of bits in prng
    537 
    538     // First, check the largest_prng value
    539     uint64_t largest_prng_value = (static_cast<uint64_t>(1)<<48) - 1;
    540     double q = (largest_prng_value >> (prng_mod_power - 26)) + 1.0;
    541     LOG(INFO) << StringPrintf("q = %f\n", q);
    542     LOG(INFO) << StringPrintf("FastLog2(q) = %f\n", sampler.FastLog2(q));
    543     LOG(INFO) << StringPrintf("log2(q) = %f\n", log(q)/log(2.0));
    544     // Replace min(sampler.FastLog2(q) - 26, 0.0) with
    545     // (sampler.FastLog2(q) - 26.000705) when using that optimization
    546     uint64_t smallest_sample_step
    547         = static_cast<uint64_t>(min(sampler.FastLog2(q) - 26, 0.0)
    548                                 * sample_scaling + 1);
    549     LOG(INFO) << "Smallest sample step is " << smallest_sample_step;
    550     uint64_t cutoff = static_cast<uint64_t>(10)
    551                       * (sample_parameter/(one<<24) + 1);
    552     LOG(INFO) << "Acceptable value is < " << cutoff;
    553     // This checks that the answer is "small" and positive
    554     CHECK_LE(smallest_sample_step, cutoff);
    555 
    556     // Next, check with the smallest prng value
    557     uint64_t smallest_prng_value = 0;
    558     q = (smallest_prng_value >> (prng_mod_power - 26)) + 1.0;
    559     LOG(INFO) << StringPrintf("q = %f\n", q);
    560     // Replace min(sampler.FastLog2(q) - 26, 0.0) with
    561     // (sampler.FastLog2(q) - 26.000705) when using that optimization
    562     uint64_t largest_sample_step
    563         = static_cast<uint64_t>(min(sampler.FastLog2(q) - 26, 0.0)
    564                                 * sample_scaling + 1);
    565     LOG(INFO) << "Largest sample step is " << largest_sample_step;
    566     CHECK_LE(largest_sample_step, one<<63);
    567     CHECK_GE(largest_sample_step, smallest_sample_step);
    568   }
    569 }
    570 
    571 
    572 // Test that NextRand is in the right range.  Unfortunately, this is a
    573 // stochastic test which could miss problems.
    574 TEST(Sampler, NextRand_range) {
    575   tcmalloc::Sampler sampler;
    576   sampler.Init(1);
    577   uint64_t one = 1;
    578   // The next number should be (one << 48) - 1
    579   uint64_t max_value = (one << 48) - 1;
    580   uint64_t x = (one << 55);
    581   int n = 22;  // 27;
    582   LOG(INFO) << "Running sampler.NextRandom 1<<" << n << " times";
    583   for (int i = 1; i <= (1<<n); i++) {  // 20 mimics sampler.Init()
    584     x = sampler.NextRandom(x);
    585     CHECK_LE(x, max_value);
    586   }
    587 }
    588 
    589 // Tests certain arithmetic operations to make sure they compute what we
    590 // expect them too (for testing across different platforms)
    591 TEST(Sampler, arithmetic_1) {
    592   tcmalloc::Sampler sampler;
    593   sampler.Init(1);
    594   uint64_t rnd;  // our 48 bit random number, which we don't trust
    595   const uint64_t prng_mod_power = 48;
    596   uint64_t one = 1;
    597   rnd = one;
    598   uint64_t max_value = (one << 48) - 1;
    599   for (int i = 1; i <= (1>>27); i++) {  // 20 mimics sampler.Init()
    600     rnd = sampler.NextRandom(rnd);
    601     CHECK_LE(rnd, max_value);
    602     double q = (rnd >> (prng_mod_power - 26)) + 1.0;
    603     CHECK_GE(q, 0); // << rnd << "  " << prng_mod_power;
    604   }
    605   // Test some potentially out of bounds value for rnd
    606   for (int i = 1; i <= 66; i++) {
    607     rnd = one << i;
    608     double q = (rnd >> (prng_mod_power - 26)) + 1.0;
    609     LOG(INFO) << "rnd = " << rnd << " i=" << i << " q=" << q;
    610     CHECK_GE(q, 0);
    611     //        << " rnd=" << rnd << "  i=" << i << " prng_mod_power" << prng_mod_power;
    612   }
    613 }
    614 
    615 void test_arithmetic(uint64_t rnd) {
    616   const uint64_t prng_mod_power = 48;  // Number of bits in prng
    617   uint64_t shifted_rnd = rnd >> (prng_mod_power - 26);
    618   CHECK_GE(shifted_rnd, 0);
    619   CHECK_LT(shifted_rnd, (1<<26));
    620   LOG(INFO) << shifted_rnd;
    621   LOG(INFO) << static_cast<double>(shifted_rnd);
    622   CHECK_GE(static_cast<double>(static_cast<uint32_t>(shifted_rnd)), 0);
    623       //      << " rnd=" << rnd << "  srnd=" << shifted_rnd;
    624   CHECK_GE(static_cast<double>(shifted_rnd), 0);
    625       //      << " rnd=" << rnd << "  srnd=" << shifted_rnd;
    626   double q = static_cast<double>(shifted_rnd) + 1.0;
    627   CHECK_GT(q, 0);
    628 }
    629 
    630 // Tests certain arithmetic operations to make sure they compute what we
    631 // expect them too (for testing across different platforms)
    632 // know bad values under with -c dbg --cpu piii for _some_ binaries:
    633 // rnd=227453640600554
    634 // shifted_rnd=54229173
    635 // (hard to reproduce)
    636 TEST(Sampler, arithmetic_2) {
    637   uint64_t rnd = 227453640600554LL;
    638   test_arithmetic(rnd);
    639 }
    640 
    641 
    642 // It's not really a test, but it's good to know
    643 TEST(Sample, size_of_class) {
    644   tcmalloc::Sampler sampler;
    645   sampler.Init(1);
    646   LOG(INFO) << "Size of Sampler class is: " << sizeof(tcmalloc::Sampler);
    647   LOG(INFO) << "Size of Sampler object is: " << sizeof(sampler);
    648 }
    649 
    650 // Make sure sampling is enabled, or the tests won't work right.
    651 DECLARE_int64(tcmalloc_sample_parameter);
    652 
    653 int main(int argc, char **argv) {
    654   if (FLAGS_tcmalloc_sample_parameter == 0)
    655     FLAGS_tcmalloc_sample_parameter = 524288;
    656   return RUN_ALL_TESTS();
    657 }
    658