| /* |
| * 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.loadtests.client; |
| |
| import java.io.IOException; |
| import java.time.Instant; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Random; |
| import org.apache.ignite.IgniteCheckedException; |
| import org.apache.ignite.internal.client.GridClient; |
| import org.apache.ignite.internal.client.GridClientConfiguration; |
| import org.apache.ignite.internal.client.GridClientData; |
| import org.apache.ignite.internal.client.GridClientDataConfiguration; |
| import org.apache.ignite.internal.client.GridClientException; |
| import org.apache.ignite.internal.client.GridClientFactory; |
| import org.apache.ignite.internal.client.GridClientPartitionAffinity; |
| import org.apache.ignite.internal.util.IgniteUtils; |
| import org.apache.ignite.internal.util.typedef.X; |
| import org.apache.ignite.internal.util.typedef.internal.U; |
| import org.apache.ignite.testframework.GridFileLock; |
| import org.apache.ignite.testframework.GridLoadTestUtils; |
| |
| /** |
| * Use {@code modules/core/src/test/config/benchmark/spring-cache-client-benchmark-*.xml} |
| * configurations for servers. |
| */ |
| public class ClientCacheBenchmark { |
| /** Number of keys, used in PUT/GET operations. */ |
| private static final int KEY_COUNT = 1000; |
| |
| /** Size of arrays used as stored values. */ |
| private static final int VALUE_LENGTH = 1024 * 4; |
| |
| /** Cached values for store. */ |
| private static final byte[][] values = new byte[KEY_COUNT][]; |
| |
| /** Probability of put operation. */ |
| private static final double WRITE_PROB = 0.2; |
| |
| /** Random generator. */ |
| private final Random rnd = new Random(); |
| |
| /** Number of submitting threads for current test. */ |
| private final int threadCnt; |
| |
| /** Number of operations per thread. */ |
| private final int iterationCnt; |
| |
| /** Test client. */ |
| private GridClient client; |
| |
| /** Resulting number of iterations per second. */ |
| private double itersPerSec; |
| |
| /** |
| * @param threadCnt Number of submitting threads. |
| * @param iterationCnt Number of operations per thread. |
| */ |
| public ClientCacheBenchmark(int threadCnt, int iterationCnt) { |
| this.threadCnt = threadCnt; |
| this.iterationCnt = iterationCnt; |
| |
| initValues(); |
| } |
| |
| /** |
| * Initiates the values cache. |
| */ |
| private void initValues() { |
| for (int i = 0; i < KEY_COUNT; i++) { |
| values[i] = new byte[VALUE_LENGTH]; |
| |
| rnd.nextBytes(values[i]); |
| } |
| } |
| |
| /** |
| * Performs test, |
| * |
| * @param printResults Whether to print results. |
| * @throws GridClientException If failed. |
| */ |
| public void run(boolean printResults) throws GridClientException { |
| Collection<TestThread> workers = new ArrayList<>(threadCnt); |
| |
| client = GridClientFactory.start(configuration()); |
| |
| long startTime = System.currentTimeMillis(); |
| |
| for (int i = 0; i < threadCnt; i++) { |
| TestThread th = new TestThread(); |
| workers.add(th); |
| th.start(); |
| } |
| |
| U.joinThreads(workers, null); |
| |
| if (printResults) |
| countAndPrintSummary(workers, startTime); |
| |
| GridClientFactory.stopAll(); |
| } |
| |
| /** |
| * @return Resulting iterations per second. |
| */ |
| public double getItersPerSec() { |
| return itersPerSec; |
| } |
| |
| /** |
| * Counts and prints tests summary, |
| * |
| * @param workers Collection of test worker threads. |
| * @param startTime Time when test eas started. |
| */ |
| private void countAndPrintSummary(Collection<TestThread> workers, long startTime) { |
| long total = 0; |
| |
| int thCnt = workers.size(); |
| |
| for (TestThread t : workers) { total += t.iters; } |
| |
| double timeSpent = ((double)(System.currentTimeMillis() - startTime)) / 1000; |
| |
| itersPerSec = total / timeSpent; |
| |
| System.out.printf("%8s, %12.0f, %12.0f, %12s\n", thCnt, itersPerSec, total / timeSpent / thCnt, total); |
| } |
| |
| /** |
| * @return Test client configuration. |
| */ |
| private GridClientConfiguration configuration() { |
| GridClientConfiguration cfg = new GridClientConfiguration(); |
| |
| cfg.setServers(Collections.singleton("localhost:11211")); |
| |
| GridClientDataConfiguration cacheCfg = new GridClientDataConfiguration(); |
| |
| cacheCfg.setName("partitioned"); |
| |
| cacheCfg.setAffinity(new GridClientPartitionAffinity()); |
| |
| cfg.setDataConfigurations(Collections.singletonList(cacheCfg)); |
| |
| return cfg; |
| } |
| |
| /** |
| * Test thread. |
| */ |
| private class TestThread extends Thread { |
| /** Thread private random generator. */ |
| private final Random rnd = new Random(); |
| |
| /** Number of iterations to perform. */ |
| private long iters; |
| |
| /** {@inheritDoc} */ |
| @Override public void run() { |
| try { |
| GridClientData data = client.data("partitioned"); |
| |
| for (int i = 0; i < iterationCnt; i++) |
| performIteration(data); |
| } |
| catch (GridClientException e) { |
| e.printStackTrace(); |
| } |
| } |
| |
| /** |
| * Performs test iteration. |
| * @param data client data to operate on. |
| * @throws GridClientException If failed. |
| */ |
| private void performIteration(GridClientData data) throws GridClientException { |
| if (rnd.nextDouble() <= WRITE_PROB) |
| data.put(rnd.nextInt(KEY_COUNT), values[rnd.nextInt(KEY_COUNT)]); |
| else |
| data.get(rnd.nextInt(KEY_COUNT)); |
| |
| iters++; |
| } |
| } |
| |
| /** |
| * Runs benchmark. |
| * @param args Command-line arguments. |
| * @throws GridClientException If failed. |
| */ |
| public static void main(String[] args) throws GridClientException, IgniteCheckedException { |
| GridFileLock fileLock = GridLoadTestUtils.fileLock(); |
| |
| fileLock.lock(); |
| |
| try { |
| System.out.printf("%8s, %12s, %12s, %12s\n", "Threads", "It./s.", "It./s.*th.", "Iters."); |
| |
| if (args.length == 0) { |
| for (int i = 1; i <= 16; i *= 2) { |
| ClientCacheBenchmark benchmark = new ClientCacheBenchmark(i, 10000); |
| |
| benchmark.run(false); |
| |
| System.gc(); |
| } |
| |
| for (int i = 1; i <= 64; i *= 2) { |
| ClientCacheBenchmark benchmark = new ClientCacheBenchmark(i, 10000); |
| |
| benchmark.run(true); |
| |
| System.gc(); |
| } |
| } |
| else { |
| int nThreads = Integer.parseInt(args[0]); |
| String outputFileName = (args.length >= 2 ? args[1] : null); |
| |
| ClientCacheBenchmark benchmark = null; |
| |
| for (int i = 0; i < 2; i++) { |
| benchmark = new ClientCacheBenchmark(nThreads, 10000); |
| |
| benchmark.run(true); |
| } |
| |
| if (outputFileName != null) { |
| X.println("Writing test results to a file: " + outputFileName); |
| |
| assert benchmark != null; |
| |
| try { |
| GridLoadTestUtils.appendLineToFile( |
| outputFileName, |
| "%s,%d", |
| IgniteUtils.LONG_DATE_FMT.format(Instant.now()), |
| Math.round(benchmark.getItersPerSec())); |
| } |
| catch (IOException e) { |
| X.error("Failed to output to a file", e); |
| } |
| } |
| } |
| } |
| finally { |
| fileLock.close(); |
| } |
| } |
| } |