Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2003, 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 // Author: Sanjay Ghemawat
     32 //
     33 // Test speed of handling fragmented heap
     34 
     35 #include "config_for_unittests.h"
     36 #include <stdlib.h>
     37 #include <stdio.h>
     38 #ifdef HAVE_SYS_RESOURCE_H
     39 #include <sys/time.h>           // for struct timeval
     40 #include <sys/resource.h>       // for getrusage
     41 #endif
     42 #ifdef _WIN32
     43 #include <windows.h>            // for GetTickCount()
     44 #endif
     45 #include <vector>
     46 #include "base/logging.h"
     47 #include "common.h"
     48 #include <gperftools/malloc_extension.h>
     49 
     50 using std::vector;
     51 
     52 int main(int argc, char** argv) {
     53   // Make kAllocSize one page larger than the maximum small object size.
     54   static const int kAllocSize = kMaxSize + kPageSize;
     55   // Allocate 400MB in total.
     56   static const int kTotalAlloc = 400 << 20;
     57   static const int kAllocIterations = kTotalAlloc / kAllocSize;
     58 
     59   // Allocate lots of objects
     60   vector<char*> saved(kAllocIterations);
     61   for (int i = 0; i < kAllocIterations; i++) {
     62     saved[i] = new char[kAllocSize];
     63   }
     64 
     65   // Check the current "slack".
     66   size_t slack_before;
     67   MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
     68                                                   &slack_before);
     69 
     70   // Free alternating ones to fragment heap
     71   size_t free_bytes = 0;
     72   for (int i = 0; i < saved.size(); i += 2) {
     73     delete[] saved[i];
     74     free_bytes += kAllocSize;
     75   }
     76 
     77   // Check that slack delta is within 10% of expected.
     78   size_t slack_after;
     79   MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
     80                                                   &slack_after);
     81   CHECK_GE(slack_after, slack_before);
     82   size_t slack = slack_after - slack_before;
     83 
     84   CHECK_GT(double(slack), 0.9*free_bytes);
     85   CHECK_LT(double(slack), 1.1*free_bytes);
     86 
     87   // Dump malloc stats
     88   static const int kBufSize = 1<<20;
     89   char* buffer = new char[kBufSize];
     90   MallocExtension::instance()->GetStats(buffer, kBufSize);
     91   VLOG(1, "%s", buffer);
     92   delete[] buffer;
     93 
     94   // Now do timing tests
     95   for (int i = 0; i < 5; i++) {
     96     static const int kIterations = 100000;
     97 #ifdef HAVE_SYS_RESOURCE_H
     98     struct rusage r;
     99     getrusage(RUSAGE_SELF, &r);    // figure out user-time spent on this
    100     struct timeval tv_start = r.ru_utime;
    101 #elif defined(_WIN32)
    102     long long int tv_start = GetTickCount();
    103 #else
    104 # error No way to calculate time on your system
    105 #endif
    106 
    107     for (int i = 0; i < kIterations; i++) {
    108       size_t s;
    109       MallocExtension::instance()->GetNumericProperty("tcmalloc.slack_bytes",
    110                                                       &s);
    111     }
    112 
    113 #ifdef HAVE_SYS_RESOURCE_H
    114     getrusage(RUSAGE_SELF, &r);
    115     struct timeval tv_end = r.ru_utime;
    116     int64 sumsec = static_cast<int64>(tv_end.tv_sec) - tv_start.tv_sec;
    117     int64 sumusec = static_cast<int64>(tv_end.tv_usec) - tv_start.tv_usec;
    118 #elif defined(_WIN32)
    119     long long int tv_end = GetTickCount();
    120     int64 sumsec = (tv_end - tv_start) / 1000;
    121     // Resolution in windows is only to the millisecond, alas
    122     int64 sumusec = ((tv_end - tv_start) % 1000) * 1000;
    123 #else
    124 # error No way to calculate time on your system
    125 #endif
    126     fprintf(stderr, "getproperty: %6.1f ns/call\n",
    127             (sumsec * 1e9 + sumusec * 1e3) / kIterations);
    128   }
    129 
    130   printf("PASS\n");
    131   return 0;
    132 }
    133