/**
* Copyright (C) 2014-2016 LinkedIn Corp. (pinot-core@linkedin.com)
*
* 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.linkedin.pinot.core.realtime.impl.dictionary;
import com.linkedin.pinot.core.segment.index.readers.Dictionary;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;
/**
* Test the performance on {@link IntOnHeapMutableDictionary} vs {@link IntBiMapDictionary}.
*/
public class DictionaryPerfRunner {
private static final Runtime RUNTIME = Runtime.getRuntime();
private static final int NUM_VALUES = 5_000_000;
private static final int NUM_READERS = 5;
private static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(NUM_READERS);
/**
* Test the performance for value indexing, dictId fetching and value fetching.
* <p>We first index all values into the dictionary, then fetch dictIds and values from it.
* <p>Test both CPU (including random) and memory usage.
*/
private static void readWritePerfOnCardinality(int cardinality) {
IntBiMapDictionary intBiMapDictionary = new IntBiMapDictionary("DummyColumn");
IntOnHeapMutableDictionary intOnHeapMutableDictionary = new IntOnHeapMutableDictionary();
System.out.println("Starting read write perf on cardinality: " + cardinality + " for " + NUM_VALUES + " values");
RUNTIME.gc();
long usedMemory = RUNTIME.totalMemory();
long start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intBiMapDictionary.index(i % cardinality);
}
System.out.println("Index time for IntBiMapDictionary: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intBiMapDictionary.indexOf(i % cardinality);
}
System.out.println("DictId fetching time for IntBiMapDictionary: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intBiMapDictionary.get(i % cardinality);
}
System.out.println("Value fetching time for IntBiMapDictionary: " + (System.currentTimeMillis() - start));
System.out.println("Memory usage for IntBiMapDictionary: " + (RUNTIME.totalMemory() - usedMemory));
System.out.println("--------------------------------------------------------------------------------");
usedMemory = RUNTIME.totalMemory();
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intOnHeapMutableDictionary.index(i % cardinality);
}
System.out.println("Index time for IntOnHeapMutableDictionary: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intOnHeapMutableDictionary.indexOf(i % cardinality);
}
System.out.println("DictId fetching time for IntOnHeapMutableDictionary: " + (System.currentTimeMillis() - start));
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
intOnHeapMutableDictionary.get(i % cardinality);
}
System.out.println("Value fetching time for IntOnHeapMutableDictionary: " + (System.currentTimeMillis() - start));
System.out.println("Memory usage for IntOnHeapMutableDictionary: " + (RUNTIME.totalMemory() - usedMemory));
}
/**
* Test the performance for multi-readers dictId fetching and value fetching.
* <p>We first index all values into the dictionary, then fetch dictIds and values from it.
*/
private static void multiReadersPerfOnCardinality(final int cardinality)
throws InterruptedException {
final IntBiMapDictionary intBiMapDictionary = new IntBiMapDictionary("DummyColumn");
final IntOnHeapMutableDictionary intOnHeapMutableDictionary = new IntOnHeapMutableDictionary();
System.out.println(
"Starting multi-readers perf on cardinality: " + cardinality + " for " + NUM_VALUES + " values with "
+ NUM_READERS + " readers");
// Index all values
for (int i = 0; i < cardinality; i++) {
intBiMapDictionary.index(i);
intOnHeapMutableDictionary.index(i);
}
// Count dictId and value fetching time
countMultiReadersFetchingTime(cardinality, intBiMapDictionary);
System.out.println("--------------------------------------------------------------------------------");
countMultiReadersFetchingTime(cardinality, intOnHeapMutableDictionary);
}
private static void countMultiReadersFetchingTime(final int cardinality, final Dictionary dictionary)
throws InterruptedException {
final CountDownLatch countDownLatch = new CountDownLatch(NUM_READERS);
final AtomicLong dictIdFetchingTime = new AtomicLong();
final AtomicLong valueFetchingTime = new AtomicLong();
for (int i = 0; i < NUM_READERS; i++) {
EXECUTOR_SERVICE.execute(new Runnable() {
@Override
public void run() {
long start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
dictionary.indexOf(i % cardinality);
}
dictIdFetchingTime.addAndGet(System.currentTimeMillis() - start);
start = System.currentTimeMillis();
for (int i = 0; i < NUM_VALUES; i++) {
dictionary.get(i % cardinality);
}
valueFetchingTime.addAndGet(System.currentTimeMillis() - start);
countDownLatch.countDown();
}
});
}
countDownLatch.await();
System.out.println(
"Total dictId fetching time for " + dictionary.getClass().getSimpleName() + ": " + dictIdFetchingTime);
System.out.println(
"Total value fetching time for " + dictionary.getClass().getSimpleName() + ": " + valueFetchingTime);
}
public static void main(String[] args)
throws InterruptedException {
int cardinality = Integer.parseInt(args[0]);
System.out.println("--------------------------------------------------------------------------------");
readWritePerfOnCardinality(cardinality);
System.out.println("--------------------------------------------------------------------------------");
System.out.println("--------------------------------------------------------------------------------");
multiReadersPerfOnCardinality(cardinality);
System.out.println("--------------------------------------------------------------------------------");
EXECUTOR_SERVICE.shutdown();
}
}