Home | History | Annotate | Download | only in benchmarks
      1 /*
      2  * Copyright (C) 2012 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <errno.h>
     18 #include <stdio.h>
     19 #include <stdlib.h>
     20 #include <unistd.h>
     21 
     22 #include <string>
     23 
     24 #if defined(__BIONIC__)
     25 
     26 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     27 #include <sys/_system_properties.h>
     28 
     29 #include <benchmark/Benchmark.h>
     30 
     31 extern void* __system_property_area__;
     32 
     33 // Do not exceed 512, that is about the largest number of properties
     34 // that can be created with the current property area size.
     35 #define TEST_NUM_PROPS \
     36     Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)
     37 
     38 struct LocalPropertyTestState {
     39   LocalPropertyTestState(int nprops) : nprops(nprops), valid(false) {
     40     static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";
     41 
     42     const char* android_data = getenv("ANDROID_DATA");
     43     if (android_data == NULL) {
     44       printf("ANDROID_DATA environment variable not set\n");
     45       return;
     46     }
     47     char dir_template[PATH_MAX];
     48     snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
     49     char* dirname = mkdtemp(dir_template);
     50     if (!dirname) {
     51       printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
     52              android_data, strerror(errno));
     53       return;
     54     }
     55 
     56     old_pa = __system_property_area__;
     57     __system_property_area__ = NULL;
     58 
     59     pa_dirname = dirname;
     60     pa_filename = pa_dirname + "/__properties__";
     61 
     62     __system_property_set_filename(pa_filename.c_str());
     63     __system_property_area_init();
     64 
     65     names = new char* [nprops];
     66     name_lens = new int[nprops];
     67     values = new char* [nprops];
     68     value_lens = new int[nprops];
     69 
     70     srandom(nprops);
     71 
     72     for (int i = 0; i < nprops; i++) {
     73       // Make sure the name has at least 10 characters to make
     74       // it very unlikely to generate the same random name.
     75       name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
     76       names[i] = new char[PROP_NAME_MAX + 1];
     77       size_t prop_name_len = sizeof(prop_name_chars) - 1;
     78       for (int j = 0; j < name_lens[i]; j++) {
     79         if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
     80           // Certain values are not allowed:
     81           // - Don't start name with '.'
     82           // - Don't allow '.' to appear twice in a row
     83           // - Don't allow the name to end with '.'
     84           // This assumes that '.' is the last character in the
     85           // array so that decrementing the length by one removes
     86           // the value from the possible values.
     87           prop_name_len--;
     88         }
     89         names[i][j] = prop_name_chars[random() % prop_name_len];
     90       }
     91       names[i][name_lens[i]] = 0;
     92 
     93       // Make sure the value contains at least 1 character.
     94       value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
     95       values[i] = new char[PROP_VALUE_MAX];
     96       for (int j = 0; j < value_lens[i]; j++) {
     97         values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
     98       }
     99 
    100       if (__system_property_add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
    101         printf("Failed to add a property, terminating...\n");
    102         printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
    103         exit(1);
    104       }
    105     }
    106 
    107     valid = true;
    108   }
    109 
    110   ~LocalPropertyTestState() {
    111     if (!valid)
    112       return;
    113 
    114     __system_property_area__ = old_pa;
    115 
    116     __system_property_set_filename(PROP_FILENAME);
    117     unlink(pa_filename.c_str());
    118     rmdir(pa_dirname.c_str());
    119 
    120     for (int i = 0; i < nprops; i++) {
    121       delete names[i];
    122       delete values[i];
    123     }
    124     delete[] names;
    125     delete[] name_lens;
    126     delete[] values;
    127     delete[] value_lens;
    128   }
    129 public:
    130   const int nprops;
    131   char** names;
    132   int* name_lens;
    133   char** values;
    134   int* value_lens;
    135   bool valid;
    136 
    137 private:
    138   std::string pa_dirname;
    139   std::string pa_filename;
    140   void* old_pa;
    141 };
    142 
    143 BENCHMARK_WITH_ARG(BM_property_get, int)->TEST_NUM_PROPS;
    144 void BM_property_get::Run(int iters, int nprops) {
    145   StopBenchmarkTiming();
    146 
    147   LocalPropertyTestState pa(nprops);
    148   char value[PROP_VALUE_MAX];
    149 
    150   if (!pa.valid)
    151     return;
    152 
    153   srandom(iters * nprops);
    154 
    155   StartBenchmarkTiming();
    156 
    157   for (int i = 0; i < iters; i++) {
    158     __system_property_get(pa.names[random() % nprops], value);
    159   }
    160   StopBenchmarkTiming();
    161 }
    162 
    163 BENCHMARK_WITH_ARG(BM_property_find, int)->TEST_NUM_PROPS;
    164 void BM_property_find::Run(int iters, int nprops) {
    165   StopBenchmarkTiming();
    166 
    167   LocalPropertyTestState pa(nprops);
    168 
    169   if (!pa.valid)
    170     return;
    171 
    172   srandom(iters * nprops);
    173 
    174   StartBenchmarkTiming();
    175 
    176   for (int i = 0; i < iters; i++) {
    177     __system_property_find(pa.names[random() % nprops]);
    178   }
    179   StopBenchmarkTiming();
    180 }
    181 
    182 BENCHMARK_WITH_ARG(BM_property_read, int)->TEST_NUM_PROPS;
    183 void BM_property_read::Run(int iters, int nprops) {
    184   StopBenchmarkTiming();
    185 
    186   LocalPropertyTestState pa(nprops);
    187 
    188   if (!pa.valid)
    189     return;
    190 
    191   srandom(iters * nprops);
    192   const prop_info** pinfo = new const prop_info*[iters];
    193   char propvalue[PROP_VALUE_MAX];
    194 
    195   for (int i = 0; i < iters; i++) {
    196     pinfo[i] = __system_property_find(pa.names[random() % nprops]);
    197   }
    198 
    199   StartBenchmarkTiming();
    200   for (int i = 0; i < iters; i++) {
    201     __system_property_read(pinfo[i], 0, propvalue);
    202   }
    203   StopBenchmarkTiming();
    204 
    205   delete[] pinfo;
    206 }
    207 
    208 BENCHMARK_WITH_ARG(BM_property_serial, int)->TEST_NUM_PROPS;
    209 void BM_property_serial::Run(int iters, int nprops) {
    210   StopBenchmarkTiming();
    211 
    212   LocalPropertyTestState pa(nprops);
    213 
    214   if (!pa.valid)
    215     return;
    216 
    217   srandom(iters * nprops);
    218   const prop_info** pinfo = new const prop_info*[iters];
    219 
    220   for (int i = 0; i < iters; i++) {
    221     pinfo[i] = __system_property_find(pa.names[random() % nprops]);
    222   }
    223 
    224   StartBenchmarkTiming();
    225   for (int i = 0; i < iters; i++) {
    226     __system_property_serial(pinfo[i]);
    227   }
    228   StopBenchmarkTiming();
    229 
    230   delete[] pinfo;
    231 }
    232 
    233 #endif  // __BIONIC__
    234