de.unentscheidbar.csv2.CaseInsensitiveBenchmark.java Source code

Java tutorial

Introduction

Here is the source code for de.unentscheidbar.csv2.CaseInsensitiveBenchmark.java

Source

/*
 * Copyright 2015 Daniel Huss
 *
 * 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 de.unentscheidbar.csv2;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Warmup;

import de.unentscheidbar.csv2.AliasedColumns;
import de.unentscheidbar.csv2.ColumnNaming;

/**
 * {@link ColumnNaming#caseInsensitive()} and {@link ColumnNaming#weaklyCaseInsensitive()} should not be slower than
 * general-purpose {@link CaseInsensitiveMap}, even when dealing with ASCII-only column names.
 */
@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 10)
@Measurement(iterations = 10)
@Fork(1)
@SuppressWarnings("javadoc")
public class CaseInsensitiveBenchmark {

    static final String safeChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    static final Collection<String> lotsOfColumnNames = getLotsOfColumnNames();
    static final String invalidKey = "_____________________________________";

    @Benchmark
    public void ciMap() {

        CaseInsentiveMapData data = caseInsensitiveMapData;
        for (String key : data.keys.get(data.rnd.nextInt(data.keys.size()))) {
            if (data.map.get(key) == null)
                throw new AssertionError(key);
        }
        if (data.map.get(invalidKey) != null)
            throw new AssertionError();
    }

    @Benchmark
    public void ciColumnNaming() {

        run(caseInsensitiveColumnNamingData);
    }

    @Benchmark
    public void weakCiColumnNaming() {

        run(weaklyCaseInsensitiveColumnNamingData);
    }

    private void run(ColumnNamingData data) {

        for (String key : data.keys.get(data.rnd.nextInt(data.keys.size()))) {
            if (data.cols.getIndex(key) == null)
                throw new AssertionError(key);
        }
        if (data.cols.getIndex(invalidKey) != null)
            throw new AssertionError();
    }

    private static final CaseInsentiveMapData caseInsensitiveMapData = new CaseInsentiveMapData();
    private static final ColumnNamingData weaklyCaseInsensitiveColumnNamingData = new ColumnNamingData(
            ColumnNaming.weaklyCaseInsensitive());
    private static final ColumnNamingData caseInsensitiveColumnNamingData = new ColumnNamingData(
            ColumnNaming.caseInsensitive());

    static final class ColumnNamingData {

        final AliasedColumns cols;
        final List<String[]> keys;
        final Random rnd = new Random(0);

        ColumnNamingData(ColumnNaming naming) {

            Map<String, Integer> temp = new HashMap<>();
            keys = new ArrayList<>();
            int i = 0;
            for (String key : lotsOfColumnNames) {
                temp.put(key, i);
                String[] variants = { key, key.toLowerCase(Locale.UK), key.toUpperCase(Locale.UK) };
                keys.add(variants);
            }
            cols = new AliasedColumns(temp, temp, naming);
        }
    }

    static final class CaseInsentiveMapData {

        final CaseInsensitiveMap<String, Integer> map;
        final List<String[]> keys;
        final Random rnd = new Random(0);

        CaseInsentiveMapData() {

            this.keys = new ArrayList<>(lotsOfColumnNames.size());
            this.map = new CaseInsensitiveMap<>(lotsOfColumnNames.size());
            int i = 0;
            for (String key : lotsOfColumnNames) {
                map.put(key, i);
                String[] variants = { key, key.toLowerCase(Locale.UK), key.toUpperCase(Locale.UK) };
                keys.add(variants);
            }
        }
    }

    static Collection<String> getLotsOfColumnNames() {

        Random rnd = new Random(0);
        Set<String> names = Collections.newSetFromMap(new CaseInsensitiveMap<String, Boolean>());
        while (names.size() < 100) {
            names.add(randomString(rnd, 1 + rnd.nextInt(30)));
        }
        List<String> uniqueNames = new ArrayList<>(names);
        /* For predictable iteration order: */
        Collections.sort(uniqueNames);
        Collections.shuffle(uniqueNames, rnd);
        return Collections.unmodifiableList(uniqueNames);
    }

    static final String randomString(Random rnd, int length) {

        StringBuilder b = new StringBuilder(length);
        for (int i = 0; i < length; i++) {
            b.append(safeChars.charAt(rnd.nextInt(safeChars.length())));
        }
        return b.toString();
    }
}