/* * Copyright (c) 2014, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * * Neither the name of Oracle nor the names of its contributors may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ package org.openjdk; import org.openjdk.jmh.annotations.*; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; @Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) @Fork(value = 3, jvmArgsAppend = "-XX:LoopUnrollLimit=1") @State(Scope.Benchmark) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.MICROSECONDS) public class Bool2Int { Boolean[] bs; @Param("100000") int size; @Param({"0.00", "0.01", "0.10", "0.50"}) double bias; @Setup public void setup() { bs = new Boolean[size]; for (int c = 0; c < size; c++) { bs[c] = (ThreadLocalRandom.current().nextInt(1000) < 1000 * bias); } } @Benchmark public int test() { int s = 0; for (Boolean b : bs) { s += b ? 1 : 0; } return s; } /* On Atom Z530, JDK 9 x86, out-of-box options: Benchmark (bias) (size) Mode Cnt Score Error Units Bool2Int.test 0.00 100000 avgt 15 661.809 ± 0.849 us/op Bool2Int.test 0.01 100000 avgt 15 602.251 ± 1.281 us/op Bool2Int.test 0.10 100000 avgt 15 602.027 ± 1.103 us/op Bool2Int.test 0.50 100000 avgt 15 602.210 ± 1.149 us/op The test with bias=0.0 is significantly slower than other biases, because the uncommon branch got folded into uncommon trap, and broken the strength reduction (?): 2.67% 5.02% ↗ 0xaedc3f40: lea 0x4(%esi,%edi,4),%ebp 2.84% 2.84% │ 0xaedc3f44: mov %ecx,%edi 0.18% 0.18% │ 0xaedc3f46: mov 0xc(%ebp),%ecx ;*aaload │ ; - org.openjdk.Bool2Int::test@22 (line 66) 4.03% 3.96% │ 0xaedc3f49: movzbl 0x8(%ecx),%edx ;*getfield value │ ; - java.lang.Boolean::booleanValue@1 (line 132) │ ; - org.openjdk.Bool2Int::test@28 (line 67) │ ; implicit exception: dispatches to 0xaedc3f95 7.91% 10.22% │ 0xaedc3f4d: test %edx,%edx 2.60% 0.51% │ 0xaedc3f4f: jne 0xaedc3f63 ;*ifeq │ ; - org.openjdk.Bool2Int::test@31 (line 67) 2.64% 0.68% │ 0xaedc3f51: mov %edi,%ecx 0.23% 0.25% │ 0xaedc3f53: inc %ecx ;*iinc │ ; - org.openjdk.Bool2Int::test@41 (line 66) 2.70% 2.96% │ 0xaedc3f54: cmp %ebx,%ecx 2.68% 2.98% ╰ 0xaedc3f56: jl 0xaedc3f40 ;*iload_1 ; - org.openjdk.Bool2Int::test@47 (line 69) Other biases fold the bool2int conversion nicely: 2.72% 3.06% ↗ 0xaedc5240: lea 0x4(%ebp,%esi,4),%ecx ;*aaload │ ; - org.openjdk.Bool2Int::test@22 (line 66) 2.87% 5.56% │ 0xaedc5244: mov %edi,%esi ;*aload_2 │ ; - org.openjdk.Bool2Int::test@19 (line 66) 0.21% 0.22% │ 0xaedc5246: mov 0xc(%ecx),%ebx ;*aaload │ ; - org.openjdk.Bool2Int::test@22 (line 66) 4.35% 4.52% │ 0xaedc5249: movzbl 0x8(%ebx),%ecx ; implicit exception: dispatches to 0xaedc5279 8.48% 10.52% │ 0xaedc524d: add %ecx,%eax ;*iadd │ ; - org.openjdk.Bool2Int::test@39 (line 67) 2.81% 2.68% │ 0xaedc524f: mov %esi,%edi 0.23% 0.20% │ 0xaedc5251: inc %edi ;*iinc │ ; - org.openjdk.Bool2Int::test@41 (line 66) 2.74% 0.70% │ 0xaedc5252: cmp %edx,%edi 2.74% 0.80% ╰ 0xaedc5254: jl 0xaedc5240 ;*if_icmpge ; - org.openjdk.Bool2Int::test@16 (line 66) */ }