1 /*
2  * Copyright (C) 2013 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.math;
18 
19 import com.google.caliper.BeforeExperiment;
20 import com.google.caliper.Benchmark;
21 import com.google.caliper.Param;
22 import java.util.Random;
23 
24 /**
25  * Benchmarks for various ways of writing the expression {@code foo + ((bar < baz) ? 1 : 0)}.
26  *
27  * @author Louis Wasserman
28  */
29 public class LessThanBenchmark {
30   static final int SAMPLE_SIZE = 0x1000;
31   static final int SAMPLE_MASK = 0x0FFF;
32 
33   @Param("1234")
34   int randomSeed;
35 
36   int[] xInts;
37   int[] yInts;
38 
39   long[] xLongs;
40   long[] yLongs;
41 
42   int[] constant;
43 
44   private static final long NONNEGATIVE_LONG_MASK = 0x7FFFFFFFFFFFFFFFL;
45 
46   @BeforeExperiment
setUp()47   void setUp() {
48     Random random = new Random(randomSeed);
49     xInts = new int[SAMPLE_SIZE];
50     yInts = new int[SAMPLE_SIZE];
51     xLongs = new long[SAMPLE_SIZE];
52     yLongs = new long[SAMPLE_SIZE];
53     constant = new int[SAMPLE_SIZE];
54     for (int i = 0; i < SAMPLE_SIZE; i++) {
55       xInts[i] = random.nextInt(Integer.MAX_VALUE);
56       yInts[i] = random.nextInt(Integer.MAX_VALUE);
57       xLongs[i] = random.nextLong() & NONNEGATIVE_LONG_MASK;
58       yLongs[i] = random.nextLong() & NONNEGATIVE_LONG_MASK;
59       constant[i] = random.nextInt();
60     }
61   }
62 
63   @Benchmark
branchFreeLtIntInlined(int reps)64   int branchFreeLtIntInlined(int reps) {
65     int tmp = 0;
66     for (int i = 0; i < reps; i++) {
67       int j = i & SAMPLE_MASK;
68       int x = xInts[j];
69       int y = yInts[j];
70       int z = constant[j];
71       tmp += z + ((x - y) >>> (Integer.SIZE - 1));
72     }
73     return tmp;
74   }
75 
76   @Benchmark
branchFreeLtInt(int reps)77   int branchFreeLtInt(int reps) {
78     int tmp = 0;
79     for (int i = 0; i < reps; i++) {
80       int j = i & SAMPLE_MASK;
81       int x = xInts[j];
82       int y = yInts[j];
83       int z = constant[j];
84       tmp += z + IntMath.lessThanBranchFree(x, y);
85     }
86     return tmp;
87   }
88 
89   @Benchmark
ternaryLtIntAddOutsideTernary(int reps)90   int ternaryLtIntAddOutsideTernary(int reps) {
91     int tmp = 0;
92     for (int i = 0; i < reps; i++) {
93       int j = i & SAMPLE_MASK;
94       int x = xInts[j];
95       int y = yInts[j];
96       int z = constant[j];
97       tmp += z + ((x < y) ? 1 : 0);
98     }
99     return tmp;
100   }
101 
102   @Benchmark
ternaryLtIntAddInsideTernary(int reps)103   int ternaryLtIntAddInsideTernary(int reps) {
104     int tmp = 0;
105     for (int i = 0; i < reps; i++) {
106       int j = i & SAMPLE_MASK;
107       int x = xInts[j];
108       int y = yInts[j];
109       int z = constant[j];
110       tmp += (x < y) ? z + 1 : z;
111     }
112     return tmp;
113   }
114 
115   @Benchmark
branchFreeLtLongInlined(int reps)116   int branchFreeLtLongInlined(int reps) {
117     int tmp = 0;
118     for (int i = 0; i < reps; i++) {
119       int j = i & SAMPLE_MASK;
120       long x = xLongs[j];
121       long y = yLongs[j];
122       int z = constant[j];
123       tmp += z + (int) ((x - y) >>> (Long.SIZE - 1));
124     }
125     return tmp;
126   }
127 
128   @Benchmark
branchFreeLtLong(int reps)129   int branchFreeLtLong(int reps) {
130     int tmp = 0;
131     for (int i = 0; i < reps; i++) {
132       int j = i & SAMPLE_MASK;
133       long x = xLongs[j];
134       long y = yLongs[j];
135       int z = constant[j];
136       tmp += z + LongMath.lessThanBranchFree(x, y);
137     }
138     return tmp;
139   }
140 
141   @Benchmark
ternaryLtLongAddOutsideTernary(int reps)142   int ternaryLtLongAddOutsideTernary(int reps) {
143     int tmp = 0;
144     for (int i = 0; i < reps; i++) {
145       int j = i & SAMPLE_MASK;
146       long x = xLongs[j];
147       long y = yLongs[j];
148       int z = constant[j];
149       tmp += z + ((x < y) ? 1 : 0);
150     }
151     return tmp;
152   }
153 
154   @Benchmark
ternaryLtLongAddInsideTernary(int reps)155   int ternaryLtLongAddInsideTernary(int reps) {
156     int tmp = 0;
157     for (int i = 0; i < reps; i++) {
158       int j = i & SAMPLE_MASK;
159       long x = xLongs[j];
160       long y = yLongs[j];
161       int z = constant[j];
162       tmp += (x < y) ? z + 1 : z;
163     }
164     return tmp;
165   }
166 }
167