/*
* 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.facebook.presto.operator.scalar;
import com.facebook.presto.spi.function.Description;
import com.facebook.presto.spi.function.ScalarFunction;
import com.facebook.presto.spi.function.SqlType;
import com.facebook.presto.spi.type.StandardTypes;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.VerboseMode;
import java.util.concurrent.TimeUnit;
@State(Scope.Thread)
@Fork(2)
@Warmup(iterations = 30, time = 500, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 30, time = 500, timeUnit = TimeUnit.MILLISECONDS)
public class BenchmarkRoundFunction
{
private double operand0;
private double operand1;
private double operand2;
private double operand3;
private double operand4;
private float floatOperand0;
private float floatOperand1;
private float floatOperand2;
private float floatOperand3;
private float floatOperand4;
@Param({"0", "1", "2", "3", "4"})
private int numberOfDecimals = 0;
@Setup
public void setup()
{
operand0 = 0.5;
operand1 = 754.1985;
operand2 = -754.2008;
operand3 = 0x1.fffffffffffffp-2;
operand4 = -0x1.fffffffffffffp-2;
floatOperand0 = 0.5f;
floatOperand1 = 754.1985f;
floatOperand2 = -754.2008f;
floatOperand3 = 0x1.fffffep-2f;
floatOperand4 = -0x1.fffffep-2f;
}
@Benchmark
public void doubleActual(Blackhole bh)
{
bh.consume(MathFunctions.round(operand0, numberOfDecimals));
bh.consume(MathFunctions.round(operand1, numberOfDecimals));
bh.consume(MathFunctions.round(operand2, numberOfDecimals));
bh.consume(MathFunctions.round(operand3, numberOfDecimals));
bh.consume(MathFunctions.round(operand4, numberOfDecimals));
}
@Benchmark
public void doubleBaseline(Blackhole bh)
{
bh.consume(roundBaseline(operand0, numberOfDecimals));
bh.consume(roundBaseline(operand1, numberOfDecimals));
bh.consume(roundBaseline(operand2, numberOfDecimals));
bh.consume(roundBaseline(operand3, numberOfDecimals));
bh.consume(roundBaseline(operand4, numberOfDecimals));
}
@Benchmark
public void floatActual(Blackhole bh)
{
bh.consume(MathFunctions.round(floatOperand0, numberOfDecimals));
bh.consume(MathFunctions.round(floatOperand1, numberOfDecimals));
bh.consume(MathFunctions.round(floatOperand2, numberOfDecimals));
bh.consume(MathFunctions.round(floatOperand3, numberOfDecimals));
bh.consume(MathFunctions.round(floatOperand4, numberOfDecimals));
}
@Benchmark
public void floatBaseline(Blackhole bh)
{
bh.consume(roundBaseline(floatOperand0, numberOfDecimals));
bh.consume(roundBaseline(floatOperand1, numberOfDecimals));
bh.consume(roundBaseline(floatOperand2, numberOfDecimals));
bh.consume(roundBaseline(floatOperand3, numberOfDecimals));
bh.consume(roundBaseline(floatOperand4, numberOfDecimals));
}
@Description("round to given number of decimal places")
@ScalarFunction
@SqlType(StandardTypes.DOUBLE)
public static double roundBaseline(@SqlType(StandardTypes.DOUBLE) double num, @SqlType(StandardTypes.BIGINT) long decimals)
{
if (num == 0.0) {
return 0;
}
if (num < 0) {
return -roundBaseline(-num, decimals);
}
double factor = Math.pow(10, decimals);
return Math.floor(num * factor + 0.5) / factor;
}
public static void main(String[] args)
throws Throwable
{
Options options = new OptionsBuilder()
.verbosity(VerboseMode.NORMAL)
.include(".*" + BenchmarkRoundFunction.class.getSimpleName() + ".*")
.build();
new Runner(options).run();
}
}