aboutsummaryrefslogtreecommitdiff
path: root/android/guava-tests/benchmark/com/google/common/primitives/UnsignedLongsBenchmark.java
blob: 288aa0c5c33c1a58bbb15e743de063479046f1fd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * Copyright (C) 2011 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.primitives;

import com.google.caliper.BeforeExperiment;
import com.google.caliper.Benchmark;
import java.util.Random;

/**
 * Benchmarks for certain methods of {@code UnsignedLongs}.
 *
 * @author Eamonn McManus
 */
public class UnsignedLongsBenchmark {
  private static final int ARRAY_SIZE = 0x10000;
  private static final int ARRAY_MASK = 0x0ffff;
  private static final Random RANDOM_SOURCE = new Random(314159265358979L);
  private static final long[] longs = new long[ARRAY_SIZE];
  private static final long[] divisors = new long[ARRAY_SIZE];
  private static final String[] decimalStrings = new String[ARRAY_SIZE];
  private static final String[] binaryStrings = new String[ARRAY_SIZE];
  private static final String[] hexStrings = new String[ARRAY_SIZE];
  private static final String[] prefixedHexStrings = new String[ARRAY_SIZE];

  @BeforeExperiment
  void setUp() {
    for (int i = 0; i < ARRAY_SIZE; i++) {
      longs[i] = random();
      divisors[i] = randomDivisor(longs[i]);
      decimalStrings[i] = UnsignedLongs.toString(longs[i]);
      binaryStrings[i] = UnsignedLongs.toString(longs[i], 2);
      hexStrings[i] = UnsignedLongs.toString(longs[i], 16);
      prefixedHexStrings[i] = "0x" + hexStrings[i];
    }
  }

  @Benchmark
  long divide(int reps) {
    long tmp = 0;
    for (int i = 0; i < reps; i++) {
      int j = i & ARRAY_MASK;
      tmp += UnsignedLongs.divide(longs[j], divisors[j]);
    }
    return tmp;
  }

  @Benchmark
  long remainder(int reps) {
    long tmp = 0;
    for (int i = 0; i < reps; i++) {
      int j = i & ARRAY_MASK;
      tmp += UnsignedLongs.remainder(longs[j], divisors[j]);
    }
    return tmp;
  }

  @Benchmark
  long parseUnsignedLong(int reps) {
    long tmp = 0;
    // Given that we make three calls per pass, we scale reps down in order
    // to do a comparable amount of work to other measurements.
    int scaledReps = reps / 3 + 1;
    for (int i = 0; i < scaledReps; i++) {
      int j = i & ARRAY_MASK;
      tmp += UnsignedLongs.parseUnsignedLong(decimalStrings[j]);
      tmp += UnsignedLongs.parseUnsignedLong(hexStrings[j], 16);
      tmp += UnsignedLongs.parseUnsignedLong(binaryStrings[j], 2);
    }
    return tmp;
  }

  @Benchmark
  long parseDecode10(int reps) {
    long tmp = 0;
    for (int i = 0; i < reps; i++) {
      int j = i & ARRAY_MASK;
      tmp += UnsignedLongs.decode(decimalStrings[j]);
    }
    return tmp;
  }

  @Benchmark
  long parseDecode16(int reps) {
    long tmp = 0;
    for (int i = 0; i < reps; i++) {
      int j = i & ARRAY_MASK;
      tmp += UnsignedLongs.decode(prefixedHexStrings[j]);
    }
    return tmp;
  }

  @Benchmark
  int toString(int reps) {
    int tmp = 0;
    // Given that we make three calls per pass, we scale reps down in order
    // to do a comparable amount of work to other measurements.
    int scaledReps = reps / 3 + 1;
    for (int i = 0; i < scaledReps; i++) {
      int j = i & ARRAY_MASK;
      long x = longs[j];
      tmp += UnsignedLongs.toString(x).length();
      tmp += UnsignedLongs.toString(x, 16).length();
      tmp += UnsignedLongs.toString(x, 2).length();
    }
    return tmp;
  }

  private static long random() {
    return RANDOM_SOURCE.nextLong();
  }

  // A random value that cannot be 0 and that is unsigned-less-than or equal
  // to the given dividend, so that we don't have half of our divisions being
  // trivial because the divisor is bigger than the dividend.
  // Using remainder here does not give us a uniform distribution but it should
  // not have a big impact on the measurement.
  private static long randomDivisor(long dividend) {
    long r = RANDOM_SOURCE.nextLong();
    if (dividend == -1) {
      return r;
    } else {
      return UnsignedLongs.remainder(r, dividend + 1);
    }
  }
}