Package com.asakusafw.runtime.stage.collector

Source Code of com.asakusafw.runtime.stage.collector.SortableSlotTest$BinaryComparator

/**
* Copyright 2011-2014 Asakusa Framework Team.
*
* 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.asakusafw.runtime.stage.collector;

import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.hadoop.io.DataInputBuffer;
import org.apache.hadoop.io.DataOutputBuffer;
import org.apache.hadoop.io.RawComparator;
import org.apache.hadoop.io.Writable;
import org.junit.Test;

import com.asakusafw.runtime.value.IntOption;

/**
* Test for {@link SortableSlot}.
*/
public class SortableSlotTest {

    /**
     * {@link SortableSlot#begin(int)}のテスト。
     */
    @Test
    public void begin() {
        SortableSlot slot = new SortableSlot();
        slot.begin(100);
        assertThat(slot.getSlot(), is(100));

        SortableSlot other = new SortableSlot();
        other.begin(101);
        assertThat(slot, is(not(other)));
    }

    /**
     * {@link SortableSlot#addByte(int)}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @Test
    public void addByte() throws Exception {
        Map<String, SortableSlot> slots = new HashMap<String, SortableSlot>();
        slots.put("min", createWithByte(Byte.MIN_VALUE));
        slots.put("min-half", createWithByte(Byte.MIN_VALUE / 2));
        slots.put("-1", createWithByte(-1));
        slots.put("0", createWithByte(0));
        slots.put("1", createWithByte(1));
        slots.put("max-half", createWithByte(Byte.MAX_VALUE / 2));
        slots.put("max", createWithByte(Byte.MAX_VALUE));

        slots.put("0,-1", createWithByte(0));
        slots.get("0,-1").addByte(-1);

        slots.put("0,0", createWithByte(0));
        slots.get("0,0").addByte(-1);

        slots.put("0,1", createWithByte(0));
        slots.get("0,1").addByte(-1);

        List<SortableSlot> copy = new ArrayList<SortableSlot>(slots.values());
        Collections.sort(copy);

        assertThat(copy.get(0), is(slots.get("min")));
        assertThat(copy.get(1), is(slots.get("min-half")));
        assertThat(copy.get(2), is(slots.get("-1")));
        assertThat(copy.get(3), is(slots.get("0")));
        assertThat(copy.get(4), is(slots.get("0,-1")));
        assertThat(copy.get(5), is(slots.get("0,0")));
        assertThat(copy.get(6), is(slots.get("0,1")));
        assertThat(copy.get(7), is(slots.get("1")));
        assertThat(copy.get(8), is(slots.get("max-half")));
        assertThat(copy.get(9), is(slots.get("max")));
    }

    private SortableSlot createWithByte(int value) throws IOException {
        SortableSlot slot = new SortableSlot();
        slot.begin(0);
        slot.addByte(value - Byte.MIN_VALUE);
        return slot;
    }

    /**
     * {@link SortableSlot#addRandom()}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @Test
    public void addRandom() throws Exception {
        SortableSlot slot = new SortableSlot();
        slot.begin(100);
        slot.addRandom();
        int same = 0;
        for (int i = 0; i < 100000; i++) {
            SortableSlot random = new SortableSlot();
            random.begin(100);
            random.addRandom();
            if (slot.equals(random)) {
                same++;
            }
        }
        assertThat(same, lessThan(100));
    }

    /**
     * {@link SortableSlot#add(Writable)}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @Test
    public void add() throws Exception {
        Map<String, SortableSlot> slots = new HashMap<String, SortableSlot>();
        slots.put("0", createWithInt(0));
        slots.put("-1", createWithInt(-1));
        slots.put("1", createWithInt(1));
        slots.put("min", createWithInt(Integer.MIN_VALUE));
        slots.put("max", createWithInt(Integer.MAX_VALUE));
        slots.put("null", createWithInt(null));
        slots.put("0.1", createWithInt(0));
        slots.get("0.1").add(new IntOption(1));

        List<SortableSlot> copy = new ArrayList<SortableSlot>(slots.values());
        Collections.sort(copy);

        assertThat(copy.get(0), is(slots.get("null")));
        assertThat(copy.get(1), is(slots.get("min")));
        assertThat(copy.get(2), is(slots.get("-1")));
        assertThat(copy.get(3), is(slots.get("0")));
        assertThat(copy.get(4), is(slots.get("0.1")));
        assertThat(copy.get(5), is(slots.get("1")));
        assertThat(copy.get(6), is(slots.get("max")));
    }

    private SortableSlot createWithInt(Integer value) throws IOException {
        SortableSlot slot = new SortableSlot();
        slot.begin(0);
        IntOption option;
        if (value == null) {
            option = new IntOption();
        } else {
            option = new IntOption(value);
        }
        slot.add(option);
        return slot;
    }

    /**
     * {@link Writable}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @Test
    public void writable() throws Exception {
        SortableSlot slot = new SortableSlot();
        slot.begin(1);
        slot.addByte(10);
        SortableSlot s1 = read(new SortableSlot(), write(slot));

        slot.begin(2);
        slot.addByte(20);
        SortableSlot s2 = read(new SortableSlot(), write(slot));

        SortableSlot a1 = new SortableSlot();
        a1.begin(1);
        a1.addByte(10);

        SortableSlot a2 = new SortableSlot();
        a2.begin(2);
        a2.addByte(20);

        assertThat(s1, is(a1));
        assertThat(s2, is(a2));
    }

    /**
     * {@link SortableSlot.Comparator}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @SuppressWarnings("unchecked")
    @Test
    public void comparator() throws Exception {
        LinkedList<SortableSlot> slots = new LinkedList<SortableSlot>();
        slots.add(createWithByte(Byte.MIN_VALUE));
        slots.add(createWithByte(Byte.MIN_VALUE / 2));
        slots.add(createWithByte(-1));
        slots.add(createWithByte(0));
        slots.add(createWithByte(1));
        slots.add(createWithByte(Byte.MAX_VALUE / 2));
        slots.add(createWithByte(Byte.MAX_VALUE));
        slots.add(createWithByte(0));
        slots.getLast().addByte(-1);
        slots.add(createWithByte(0));
        slots.getLast().addByte(0);
        slots.add(createWithByte(0));
        slots.getLast().addByte(1);

        LinkedList<SortableSlot> copy = new LinkedList<SortableSlot>(slots);
        Collections.sort(slots, new SortableSlot.Comparator());
        Collections.sort(copy, new BinaryComparator(new SortableSlot.Comparator()));

        assertThat(copy, is(slots));
    }

    /**
     * {@link SortableSlot.Partitioner}のテスト。
     * @throws Exception テストに失敗した場合
     */
    @Test
    public void partitioner() throws Exception {
        final int partitions = 10;
        final int records = 50000;

        SortableSlot.Partitioner partitioner = new SortableSlot.Partitioner();
        List<List<SortableSlot>> slotsParts = new ArrayList<List<SortableSlot>>();
        for (int i = 0; i < partitions; i++) {
            slotsParts.add(new ArrayList<SortableSlot>());
        }

        int lastPartition = -1;
        int partitionChanged = -1;
        int[] partitionMemberCount = new int[partitions];
        for (int i = 0; i < partitions; i++) {
            for (int j = 0; j < records; j++) {
                SortableSlot slot = new SortableSlot();
                slot.begin(i);
                slot.add(new IntOption(j));

                int partition = partitioner.getPartition(slot, null, partitions);
                partitionMemberCount[partition]++;

                // パーティションの切り替わりをカウントする
                if (lastPartition != partition) {
                    partitionChanged++;
                }
                lastPartition = partition;
            }
        }

        int max = -1;
        for (int memberCount : partitionMemberCount) {
            max = Math.max(max, memberCount);
        }

        assertThat("パーティションにメンバーが偏っている: " + Arrays.toString(partitionMemberCount),
                (double) max / records,
                lessThan(1.2));

        double sequencialReadAve = records * partitions / partitionChanged;
        assertThat("パーティションが細かい", sequencialReadAve, greaterThan(500.0));
        assertThat("パーティションが粗い", sequencialReadAve, lessThan(10000.0));
    }

    static byte[] write(Writable writable) {
        DataOutputBuffer buffer = new DataOutputBuffer();
        buffer.reset();
        try {
            writable.write(buffer);
        } catch (IOException e) {
            throw new AssertionError(e);
        }
        return Arrays.copyOf(buffer.getData(), buffer.getLength());
    }

    static <T extends Writable> T read(T writable, byte[] bytes) {
        DataInputBuffer buffer = new DataInputBuffer();
        buffer.reset(bytes, bytes.length);
        try {
            writable.readFields(buffer);
        } catch (IOException e) {
            throw new AssertionError(e);
        }
        return writable;
    }

    static class BinaryComparator implements Comparator<Writable> {

        private RawComparator<?> comparator;

        BinaryComparator(RawComparator<?> comparator) {
            this.comparator = comparator;
        }

        @Override
        public int compare(Writable o1, Writable o2) {
            byte[] b1 = write(o1);
            byte[] b2 = write(o2);
            return comparator.compare(b1, 0, b1.length, b2, 0, b2.length);
        }
    }
}
TOP

Related Classes of com.asakusafw.runtime.stage.collector.SortableSlotTest$BinaryComparator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.