Home | History | Annotate | Download | only in primitives
      1 /*
      2  * Copyright (C) 2011 The Guava Authors
      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 package com.google.common.primitives;
     18 
     19 import com.google.caliper.BeforeExperiment;
     20 import com.google.caliper.Benchmark;
     21 
     22 import java.util.Random;
     23 
     24 /**
     25  * Benchmarks for certain methods of {@code UnsignedLongs}.
     26  *
     27  * @author Eamonn McManus
     28  */
     29 public class UnsignedLongsBenchmark {
     30   private static final int ARRAY_SIZE = 0x10000;
     31   private static final int ARRAY_MASK = 0x0ffff;
     32   private static final Random RANDOM_SOURCE = new Random(314159265358979L);
     33   private static final long[] longs = new long[ARRAY_SIZE];
     34   private static final long[] divisors = new long[ARRAY_SIZE];
     35   private static final String[] decimalStrings = new String[ARRAY_SIZE];
     36   private static final String[] binaryStrings = new String[ARRAY_SIZE];
     37   private static final String[] hexStrings = new String[ARRAY_SIZE];
     38   private static final String[] prefixedHexStrings = new String[ARRAY_SIZE];
     39 
     40   @BeforeExperiment
     41   void setUp() {
     42     for (int i = 0; i < ARRAY_SIZE; i++) {
     43       longs[i] = random();
     44       divisors[i] = randomDivisor(longs[i]);
     45       decimalStrings[i] = UnsignedLongs.toString(longs[i]);
     46       binaryStrings[i] = UnsignedLongs.toString(longs[i], 2);
     47       hexStrings[i] = UnsignedLongs.toString(longs[i], 16);
     48       prefixedHexStrings[i] = "0x" + hexStrings[i];
     49     }
     50   }
     51 
     52   @Benchmark long divide(int reps) {
     53     long tmp = 0;
     54     for (int i = 0; i < reps; i++) {
     55       int j = i & ARRAY_MASK;
     56       tmp += UnsignedLongs.divide(longs[j], divisors[j]);
     57     }
     58     return tmp;
     59   }
     60 
     61   @Benchmark long remainder(int reps) {
     62     long tmp = 0;
     63     for (int i = 0; i < reps; i++) {
     64       int j = i & ARRAY_MASK;
     65       tmp += UnsignedLongs.remainder(longs[j], divisors[j]);
     66     }
     67     return tmp;
     68   }
     69 
     70   @Benchmark long parseUnsignedLong(int reps) {
     71     long tmp = 0;
     72     // Given that we make three calls per pass, we scale reps down in order
     73     // to do a comparable amount of work to other measurements.
     74     int scaledReps = reps / 3 + 1;
     75     for (int i = 0; i < scaledReps; i++) {
     76       int j = i & ARRAY_MASK;
     77       tmp += UnsignedLongs.parseUnsignedLong(decimalStrings[j]);
     78       tmp += UnsignedLongs.parseUnsignedLong(hexStrings[j], 16);
     79       tmp += UnsignedLongs.parseUnsignedLong(binaryStrings[j], 2);
     80     }
     81     return tmp;
     82   }
     83 
     84   @Benchmark long parseDecode10(int reps) {
     85     long tmp = 0;
     86     for (int i = 0; i < reps; i++) {
     87       int j = i & ARRAY_MASK;
     88       tmp += UnsignedLongs.decode(decimalStrings[j]);
     89     }
     90     return tmp;
     91   }
     92 
     93   @Benchmark long parseDecode16(int reps) {
     94     long tmp = 0;
     95     for (int i = 0; i < reps; i++) {
     96       int j = i & ARRAY_MASK;
     97       tmp += UnsignedLongs.decode(prefixedHexStrings[j]);
     98     }
     99     return tmp;
    100   }
    101 
    102   @Benchmark int toString(int reps) {
    103     int tmp = 0;
    104     // Given that we make three calls per pass, we scale reps down in order
    105     // to do a comparable amount of work to other measurements.
    106     int scaledReps = reps / 3 + 1;
    107     for (int i = 0; i < scaledReps; i++) {
    108       int j = i & ARRAY_MASK;
    109       long x = longs[j];
    110       tmp += UnsignedLongs.toString(x).length();
    111       tmp += UnsignedLongs.toString(x, 16).length();
    112       tmp += UnsignedLongs.toString(x, 2).length();
    113     }
    114     return tmp;
    115   }
    116 
    117   private static long random() {
    118     return RANDOM_SOURCE.nextLong();
    119   }
    120 
    121   // A random value that cannot be 0 and that is unsigned-less-than or equal
    122   // to the given dividend, so that we don't have half of our divisions being
    123   // trivial because the divisor is bigger than the dividend.
    124   // Using remainder here does not give us a uniform distribution but it should
    125   // not have a big impact on the measurement.
    126   private static long randomDivisor(long dividend) {
    127     long r = RANDOM_SOURCE.nextLong();
    128     if (dividend == -1) {
    129       return r;
    130     } else {
    131       return UnsignedLongs.remainder(r, dividend + 1);
    132     }
    133   }
    134 }
    135