/*
* Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved.
*
* 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.hazelcast.query.impl;
import com.hazelcast.config.Config;
import com.hazelcast.config.InMemoryFormat;
import com.hazelcast.config.MapAttributeConfig;
import com.hazelcast.config.MapConfig;
import com.hazelcast.core.IMap;
import com.hazelcast.instance.HazelcastInstanceProxy;
import com.hazelcast.nio.serialization.impl.DefaultPortableReaderQuickTest;
import com.hazelcast.query.Predicates;
import com.hazelcast.query.extractor.ValueCollector;
import com.hazelcast.query.extractor.ValueExtractor;
import com.hazelcast.query.extractor.ValueReader;
import com.hazelcast.query.impl.extractor.specification.ComplexDataStructure;
import com.hazelcast.test.HazelcastTestSupport;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import org.openjdk.jmh.runner.options.VerboseMode;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import static com.hazelcast.query.impl.extractor.specification.ComplexDataStructure.finger;
import static com.hazelcast.query.impl.extractor.specification.ComplexDataStructure.limb;
import static com.hazelcast.query.impl.extractor.specification.ComplexDataStructure.person;
import static com.hazelcast.query.impl.extractor.specification.ComplexDataStructure.tattoos;
@State(Scope.Thread)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class QueryPerformanceTest extends HazelcastTestSupport {
private static final int WARMUP_ITERATIONS_COUNT = 1000;
private static final int MEASUREMENT_ITERATIONS_COUNT = 10000;
private HazelcastInstanceProxy hz;
private IMap portableMap;
private IMap portableMapWithExtractor;
private IMap objectMap;
private IMap objectMapWithExtractor;
public static class NameExtractor extends ValueExtractor<ComplexDataStructure.Person, Object> {
@Override
public void extract(ComplexDataStructure.Person target, Object argument, ValueCollector collector) {
collector.addObject(target.getName());
}
}
public static class LimbNameExtractor extends ValueExtractor<ComplexDataStructure.Person, Object> {
@Override
public void extract(ComplexDataStructure.Person target, Object argument, ValueCollector collector) {
collector.addObject(target.getFirstLimb().getName());
}
}
public static class PortableNameExtractor extends ValueExtractor<ValueReader, Object> {
@Override
public void extract(ValueReader target, Object argument, ValueCollector collector) {
target.read("name", collector);
}
}
public static class PortableLimbNameExtractor extends ValueExtractor<ValueReader, Object> {
@Override
public void extract(ValueReader target, Object argument, ValueCollector collector) {
target.read("firstLimb.name", collector);
}
}
@Setup
public void setup() throws IOException {
Config config = new Config();
config.getSerializationConfig().addPortableFactory(DefaultPortableReaderQuickTest.TestPortableFactory.ID,
new DefaultPortableReaderQuickTest.TestPortableFactory());
//
// object map
//
MapAttributeConfig nameWithExtractor = new MapAttributeConfig();
nameWithExtractor.setName("nameWithExtractor");
nameWithExtractor.setExtractor("com.hazelcast.query.impl.QueryPerformanceTest$NameExtractor");
MapAttributeConfig limbNameWithExtractor = new MapAttributeConfig();
limbNameWithExtractor.setName("limbNameWithExtractor");
limbNameWithExtractor.setExtractor("com.hazelcast.query.impl.QueryPerformanceTest$LimbNameExtractor");
MapConfig objectMapConfig = new MapConfig();
objectMapConfig.setInMemoryFormat(InMemoryFormat.OBJECT);
objectMapConfig.setName("objectMap");
MapConfig objectMapWithExtractorConfig = new MapConfig();
objectMapWithExtractorConfig.setInMemoryFormat(InMemoryFormat.OBJECT);
objectMapWithExtractorConfig.setName("objectMapWithExtractor");
objectMapWithExtractorConfig.addMapAttributeConfig(nameWithExtractor);
objectMapWithExtractorConfig.addMapAttributeConfig(limbNameWithExtractor);
//
// portable map
//
MapAttributeConfig portableNameWithExtractor = new MapAttributeConfig();
portableNameWithExtractor.setName("nameWithExtractor");
portableNameWithExtractor.setExtractor("com.hazelcast.query.impl.QueryPerformanceTest$PortableNameExtractor");
MapAttributeConfig portableLimbNameWithExtractor = new MapAttributeConfig();
portableLimbNameWithExtractor.setName("limbNameWithExtractor");
portableLimbNameWithExtractor.setExtractor("com.hazelcast.query.impl.QueryPerformanceTest$PortableLimbNameExtractor");
MapConfig portableMapConfig = new MapConfig();
portableMapConfig.setName("portableMapWithExtractor");
portableMapConfig.addMapAttributeConfig(portableNameWithExtractor);
portableMapConfig.addMapAttributeConfig(portableLimbNameWithExtractor);
config.addMapConfig(objectMapConfig);
config.addMapConfig(objectMapWithExtractorConfig);
config.addMapConfig(portableMapConfig);
hz = (HazelcastInstanceProxy) createHazelcastInstance(config);
portableMap = hz.getMap("portableMap");
objectMap = hz.getMap("objectMap");
objectMapWithExtractor = hz.getMap("objectMapWithExtractor");
portableMapWithExtractor = hz.getMap("portableMapWithExtractor");
ComplexDataStructure.Person BOND = person("Bond",
limb("left-hand", tattoos(), finger("thumb"), finger(null)),
limb("right-hand", tattoos("knife"), finger("middle"), finger("index"))
);
for (int i = 0; i <= 1000; i++) {
portableMap.put(String.valueOf(i), BOND.getPortable());
portableMapWithExtractor.put(String.valueOf(i), BOND.getPortable());
objectMap.put(String.valueOf(i), BOND);
objectMapWithExtractor.put(String.valueOf(i), BOND);
}
}
@TearDown
public void tearDown() throws IOException {
hz.shutdown();
}
@Benchmark
public Object query_portable_equalsPredicate() throws IOException {
return portableMap.values(Predicates.equal("name", "Ferrari"));
}
@Benchmark
public Object query_portable_nested_equalsPredicate() throws IOException {
return portableMap.values(Predicates.equal("firstLimb.name", "Ferrari"));
}
@Benchmark
public Object query_portable_nested_collection_equalsPredicate() throws IOException {
return portableMap.values(Predicates.equal("limbs_portable[1].name", "Ferrari"));
}
@Benchmark
public Object query_portable_nestedTwice_collection_equalsPredicate() throws IOException {
return portableMap.values(Predicates.equal("limbs_portable[0].fingers_portable[1].name", "Ferrari"));
}
@Benchmark
public Object query_portable_extractor_equalsPredicate() throws IOException {
return portableMapWithExtractor.values(Predicates.equal("nameWithExtractor", "Ferrari"));
}
@Benchmark
public Object query_portable_extractor_nested_equalsPredicate() throws IOException {
return portableMapWithExtractor.values(Predicates.equal("limbNameWithExtractor", "Ferrari"));
}
@Benchmark
public Object query_object_equalsPredicate() throws IOException {
return objectMap.values(Predicates.equal("name", "Ferrari"));
}
@Benchmark
public Object query_object_nested_equalsPredicate() throws IOException {
return objectMap.values(Predicates.equal("firstLimb.name", "Ferrari"));
}
@Benchmark
public Object query_object_nested_collection_equalsPredicate() throws IOException {
return objectMap.values(Predicates.equal("limbs_list[1].name", "Ferrari"));
}
@Benchmark
public Object query_object_nestedTwice_collection_equalsPredicate() throws IOException {
return objectMap.values(Predicates.equal("limbs_list[0].fingers_list[1].name", "Ferrari"));
}
@Benchmark
public Object query_object_extractor_equalsPredicate() throws IOException {
return objectMapWithExtractor.values(Predicates.equal("nameWithExtractor", "Ferrari"));
}
@Benchmark
public Object query_object_extractor_nested_equalsPredicate() throws IOException {
return objectMapWithExtractor.values(Predicates.equal("limbNameWithExtractor", "Ferrari"));
}
public static void main(String[] args) throws RunnerException {
Options opt = new OptionsBuilder()
.include(QueryPerformanceTest.class.getSimpleName())
.warmupIterations(WARMUP_ITERATIONS_COUNT)
.warmupTime(TimeValue.milliseconds(2))
.measurementIterations(MEASUREMENT_ITERATIONS_COUNT)
.measurementTime(TimeValue.milliseconds(2))
.verbosity(VerboseMode.NORMAL)
.forks(1)
.build();
new Runner(opt).run();
}
}