blob: f05d321219ed48a2b00c737739b0c7ece8ddf1a4 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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 org.apache.commons.geometry.examples.jmh.euclidean;
import java.util.concurrent.TimeUnit;
import org.apache.commons.geometry.euclidean.oned.AffineTransformMatrix1D;
import org.apache.commons.geometry.euclidean.oned.Vector1D;
import org.apache.commons.geometry.euclidean.threed.AffineTransformMatrix3D;
import org.apache.commons.geometry.euclidean.threed.Vector3D;
import org.apache.commons.geometry.euclidean.twod.AffineTransformMatrix2D;
import org.apache.commons.geometry.euclidean.twod.Vector2D;
import org.apache.commons.geometry.examples.jmh.BenchmarkUtils;
import org.apache.commons.rng.UniformRandomProvider;
import org.apache.commons.rng.simple.RandomSource;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
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;
/** Benchmarks for
* {@link org.apache.commons.geometry.euclidean.AbstractAffineTransformMatrix AbstractAffineTransformMatrix}
* subclasses.
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
@Fork(value = 1, jvmArgs = {"-server", "-Xms512M", "-Xmx512M"})
public class AffineTransformMatrixPerformance {
/** Input class providing random arrays of double values for transformation.
*/
@State(Scope.Thread)
public static class TransformArrayInput {
/** The number of elements in the input array. */
@Param({"6000", "600000"})
private int size;
/** Array containing the input elements. */
private double[] array;
/** Get the configured size of the input array.
* @return the configured size of the input array
*/
public int getSize() {
return size;
}
/** Get the input array.
* @return input array
*/
public double[] getArray() {
return array;
}
/** Set up the input array.
*/
@Setup(Level.Iteration)
public void setup() {
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
array = new double[size];
for (int i = 0; i < array.length; ++i) {
array[i] = BenchmarkUtils.randomDouble(rand);
}
}
}
/** Input class providing a 1D transform matrix.
*/
@State(Scope.Thread)
public static class TransformMatrixInput1D {
/** Input transform matrix. */
private AffineTransformMatrix1D transform;
/** Get the input transform matrix.
* @return the input transform matrix
*/
public AffineTransformMatrix1D getTransform() {
return transform;
}
/** Set up the input. */
@Setup
public void setup() {
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
transform = AffineTransformMatrix1D.of(BenchmarkUtils.randomDoubleArray(rand, 2));
}
}
/** Input class providing a 2D transform matrix.
*/
@State(Scope.Thread)
public static class TransformMatrixInput2D {
/** Input transform matrix. */
private AffineTransformMatrix2D transform;
/** Get the input transform matrix.
* @return the input transform matrix
*/
public AffineTransformMatrix2D getTransform() {
return transform;
}
/** Set up the input. */
@Setup
public void setup() {
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
transform = AffineTransformMatrix2D.of(BenchmarkUtils.randomDoubleArray(rand, 6));
}
}
/** Input class providing a 3D transform matrix.
*/
@State(Scope.Thread)
public static class TransformMatrixInput3D {
/** Input transform matrix. */
private AffineTransformMatrix3D transform;
/** Get the input transform matrix.
* @return the input transform matrix
*/
public AffineTransformMatrix3D getTransform() {
return transform;
}
/** Set up the input. */
@Setup
public void setup() {
final UniformRandomProvider rand = RandomSource.create(RandomSource.XO_RO_SHI_RO_128_PP);
transform = AffineTransformMatrix3D.of(BenchmarkUtils.randomDoubleArray(rand, 12));
}
}
/** Baseline benchmark for 1D transforms on array data.
* @param arrayInput array input
* @return transformed output
*/
@Benchmark
public double[] baselineArray1D(final TransformArrayInput arrayInput) {
final double[] arr = arrayInput.getArray();
double x;
for (int i = 0; i < arr.length; ++i) {
x = arr[i];
arr[i] = x + 1;
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by converting each group
* to a Vector1D.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayAsVectors1D(final TransformArrayInput arrayInput,
final TransformMatrixInput1D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix1D t = transformInput.getTransform();
Vector1D in;
Vector1D out;
for (int i = 0; i < arr.length; ++i) {
in = Vector1D.of(arr[i]);
out = t.apply(in);
arr[i] = out.getX();
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by transforming
* the components directly.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayComponents1D(final TransformArrayInput arrayInput,
final TransformMatrixInput1D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix1D t = transformInput.getTransform();
double x;
for (int i = 0; i < arr.length; ++i) {
x = arr[i];
arr[i] = t.applyX(x);
}
return arr;
}
/** Baseline benchmark for 2D transforms on array data.
* @param arrayInput array input
* @return transformed output
*/
@Benchmark
public double[] baselineArray2D(final TransformArrayInput arrayInput) {
final double[] arr = arrayInput.getArray();
double x;
double y;
for (int i = 0; i < arr.length; i += 2) {
x = arr[i];
y = arr[i + 1];
arr[i] = x + 1;
arr[i + 1] = y + 1;
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by converting each group
* to a Vector2D.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayAsVectors2D(final TransformArrayInput arrayInput,
final TransformMatrixInput2D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix2D t = transformInput.getTransform();
Vector2D in;
Vector2D out;
for (int i = 0; i < arr.length; i += 2) {
in = Vector2D.of(
arr[i],
arr[i + 1]);
out = t.apply(in);
arr[i] = out.getX();
arr[i + 1] = out.getY();
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by transforming
* the components directly.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayComponents2D(final TransformArrayInput arrayInput,
final TransformMatrixInput2D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix2D t = transformInput.getTransform();
double x;
double y;
for (int i = 0; i < arr.length; i += 2) {
x = arr[i];
y = arr[i + 1];
arr[i] = t.applyX(x, y);
arr[i + 1] = t.applyY(x, y);
}
return arr;
}
/** Baseline benchmark for 3D transforms on array data.
* @param arrayInput array input
* @return transformed output
*/
@Benchmark
public double[] baselineArray3D(final TransformArrayInput arrayInput) {
final double[] arr = arrayInput.getArray();
double x;
double y;
double z;
for (int i = 0; i < arr.length; i += 3) {
x = arr[i];
y = arr[i + 1];
z = arr[i + 2];
arr[i] = x + 1;
arr[i + 1] = y + 1;
arr[i + 2] = z + 1;
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by converting each group
* to a Vector3D.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayAsVectors3D(final TransformArrayInput arrayInput,
final TransformMatrixInput3D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix3D t = transformInput.getTransform();
Vector3D in;
Vector3D out;
for (int i = 0; i < arr.length; i += 3) {
in = Vector3D.of(
arr[i],
arr[i + 1],
arr[i + 2]);
out = t.apply(in);
arr[i] = out.getX();
arr[i + 1] = out.getY();
arr[i + 2] = out.getZ();
}
return arr;
}
/** Benchmark testing the performance of transforming an array of doubles by transforming
* the components directly.
* @param arrayInput array input
* @param transformInput transform input
* @return transformed output
*/
@Benchmark
public double[] transformArrayComponents3D(final TransformArrayInput arrayInput,
final TransformMatrixInput3D transformInput) {
final double[] arr = arrayInput.getArray();
final AffineTransformMatrix3D t = transformInput.getTransform();
double x;
double y;
double z;
for (int i = 0; i < arr.length; i += 3) {
x = arr[i];
y = arr[i + 1];
z = arr[i + 2];
arr[i] = t.applyX(x, y, z);
arr[i + 1] = t.applyY(x, y, z);
arr[i + 2] = t.applyZ(x, y, z);
}
return arr;
}
}