/* * 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.ignite.internal.benchmarks.jmh.notify; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicLong; import javax.cache.configuration.Factory; import javax.cache.expiry.Duration; import javax.cache.expiry.ExpiryPolicy; import org.apache.ignite.IgniteDataStreamer; import org.apache.ignite.Ignition; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.internal.benchmarks.jmh.cache.JmhCacheAbstractBenchmark; import org.apache.ignite.internal.benchmarks.model.IntValue; import org.jsr166.ThreadLocalRandom8; 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.Scope; import org.openjdk.jmh.annotations.Setup; import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.infra.BenchmarkParams; import org.openjdk.jmh.results.RunResult; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; import org.openjdk.jmh.runner.options.ChainedOptionsBuilder; import org.openjdk.jmh.runner.options.OptionsBuilder; import org.openjdk.jmh.runner.options.TimeValue; /** * */ @OutputTimeUnit(TimeUnit.MICROSECONDS) @BenchmarkMode({/*Mode.AverageTime,*/ Mode.Throughput}) @Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) @Measurement(iterations = 5, time = 10, timeUnit = TimeUnit.SECONDS) @Fork(1) @State(Scope.Benchmark) public class JmhWaitStategyBenchmark extends JmhCacheAbstractBenchmark { /** */ private static class RandomExpiryPolicy implements ExpiryPolicy { /** rate duration will decrease with */ private final double rate; /** current duration. */ private final AtomicLong duration = new AtomicLong(1_000_000_000); /** */ RandomExpiryPolicy(double rate) { this.rate = rate; } /** {@inheritDoc} */ @Override public Duration getExpiryForCreation() { boolean generateEvt = ThreadLocalRandom8.current().nextDouble() < rate; return generateEvt ? new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()) : new Duration(TimeUnit.MILLISECONDS, duration.get()); } /** {@inheritDoc} */ @Override public Duration getExpiryForAccess() { boolean generateEvt = ThreadLocalRandom8.current().nextDouble() < rate; return generateEvt ? new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()) : new Duration(TimeUnit.MILLISECONDS, duration.get()); } /** {@inheritDoc} */ @Override public Duration getExpiryForUpdate() { boolean generateEvt = ThreadLocalRandom8.current().nextDouble() < rate; return generateEvt ? new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()) : new Duration(TimeUnit.MILLISECONDS, duration.get()); } } /** @param rate duration will decrease with */ private static Factory<ExpiryPolicy> getExpiryPolicyFactoryWithDecreasingRate(final double rate) { return new Factory<ExpiryPolicy>() { @Override public ExpiryPolicy create() { return new RandomExpiryPolicy(rate); } }; } /** Decreasing expiry policy. */ private static final ExpiryPolicy DECREASING_EXPIRY_POLICY = new ExpiryPolicy() { AtomicLong duration = new AtomicLong(1_000_000_000); @Override public Duration getExpiryForCreation() { return new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()); } @Override public Duration getExpiryForAccess() { return new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()); } @Override public Duration getExpiryForUpdate() { return new Duration(TimeUnit.MILLISECONDS, duration.decrementAndGet()); } }; /** Increasing expiry policy. */ private static final ExpiryPolicy INCREASING_EXPIRY_POLICY = new ExpiryPolicy() { AtomicLong duration = new AtomicLong(1_000_000); @Override public Duration getExpiryForCreation() { return new Duration(TimeUnit.MILLISECONDS, duration.incrementAndGet()); } @Override public Duration getExpiryForAccess() { return new Duration(TimeUnit.MILLISECONDS, duration.incrementAndGet()); } @Override public Duration getExpiryForUpdate() { return new Duration(TimeUnit.MILLISECONDS, duration.incrementAndGet()); } }; /** Decreasing policy factory. */ private final static Factory<ExpiryPolicy> DECREASING_POLICY_FACTORY = new Factory<ExpiryPolicy>() { @Override public ExpiryPolicy create() { return DECREASING_EXPIRY_POLICY; } }; /** Increasing policy factory. */ private final static Factory<ExpiryPolicy> INCREASING_POLICY_FACTORY = new Factory<ExpiryPolicy>() { @Override public ExpiryPolicy create() { return INCREASING_EXPIRY_POLICY; } }; /** {@inheritDoc} */ @Setup (Level.Iteration) @Override public void setup() throws Exception { Ignition.stopAll(true); super.setup(); CacheConfiguration<Object, Object> cfg = new CacheConfiguration<>(); cfg.setName("cache"); cfg.setEagerTtl(true); cfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL); String prop = System.getProperty("bench.exp.policy"); switch (prop) { case "inc": cfg.setExpiryPolicyFactory(INCREASING_POLICY_FACTORY); break; case "dec": cfg.setExpiryPolicyFactory(DECREASING_POLICY_FACTORY); break; default: assert prop.charAt(0) == 'r'; double rate = Double.parseDouble(prop.trim().substring(1)) / 100; cfg.setExpiryPolicyFactory(getExpiryPolicyFactoryWithDecreasingRate(rate)); break; } node.createCache(cfg); cache = node.getOrCreateCache("cache"); IgniteDataStreamer<Integer, IntValue> dataLdr = node.dataStreamer(cache.getName()); for (int i = 0; i < CNT; i++) dataLdr.addData(i, new IntValue(i)); dataLdr.close(); System.out.println("Cache populated."); } /** {@inheritDoc} */ @TearDown public void tearDown() throws Exception { Ignition.stopAll(true); } /** * Test PUT operation. * * @throws Exception If failed. */ @Benchmark public void put() throws Exception { int key = ThreadLocalRandom.current().nextInt(CNT); cache.put(key, new IntValue(key)); } /** * Benchmark runner */ public static void main(String[] args) throws RunnerException { List<String> policies = Arrays.asList("inc", "dec", "r25", "r50", "r75"); int[] threads = {2, 4, 8, 16, 32}; List<RunResult> results = new ArrayList<>(); for (String policy : policies) { for (int thread : threads) { ChainedOptionsBuilder builder = new OptionsBuilder() .jvmArgs() .timeUnit(TimeUnit.MILLISECONDS) .measurementIterations(10) .measurementTime(TimeValue.seconds(20)) .warmupIterations(5) .warmupTime(TimeValue.seconds(10)) .jvmArgs("-Dbench.exp.policy=" + policy) .forks(1) .threads(thread) .mode(Mode.Throughput) .include(JmhWaitStategyBenchmark.class.getSimpleName()); results.addAll(new Runner(builder.build()).run()); } } for (RunResult result : results) { BenchmarkParams params = result.getParams(); Collection<String> args1 = params.getJvmArgs(); for (String s : args1) { System.out.print(s.substring(s.length() -3, s.length())); System.out.print(" x "); } System.out.print(params.getThreads()); System.out.print("\t\t"); System.out.println(result.getPrimaryResult().toString()); } } }