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