/** * 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.hadoop.hive.ql.exec.vector.mapjoin.fast; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.Random; import org.apache.hadoop.hive.ql.exec.JoinUtil; import org.apache.hadoop.hive.ql.exec.vector.mapjoin.fast.CheckFastHashTable.VerifyFastBytesHashMap; import org.apache.hadoop.hive.ql.exec.vector.mapjoin.hashtable.VectorMapJoinHashMapResult; import org.apache.hadoop.hive.ql.metadata.HiveException; import org.junit.Test; /* * An multi-key value hash map optimized for vector map join. * * The key is uninterpreted bytes. */ public class TestVectorMapJoinFastBytesHashMap extends CommonFastHashTable { @Test public void testOneKey() throws Exception { random = new Random(82733); VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,CAPACITY, LOAD_FACTOR, WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); byte[] key = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key); byte[] value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); verifyTable.verify(map); // Second value. value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); verifyTable.verify(map); // Third value. value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); verifyTable.verify(map); } @Test public void testMultipleKeysSingleValue() throws Exception { random = new Random(29383); VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,CAPACITY, LOAD_FACTOR, WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); int keyCount = 100 + random.nextInt(1000); for (int i = 0; i < keyCount; i++) { byte[] key = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key); if (!verifyTable.contains(key)) { // Unique keys for this test. break; } byte[] value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); verifyTable.verify(map); } } @Test public void testGetNonExistent() throws Exception { random = new Random(1002); VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,CAPACITY, LOAD_FACTOR, WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); byte[] key1 = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key1); byte[] value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key1, value); verifyTable.add(key1, value); verifyTable.verify(map); byte[] key2 = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key2); VectorMapJoinHashMapResult hashMapResult = map.createHashMapResult(); JoinUtil.JoinResult joinResult = map.lookup(key2, 0, key2.length, hashMapResult); assertTrue(joinResult == JoinUtil.JoinResult.NOMATCH); assertTrue(!hashMapResult.hasRows()); map.testPutRow(key2, value); verifyTable.add(key2, value); verifyTable.verify(map); byte[] key3 = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key3); hashMapResult = map.createHashMapResult(); joinResult = map.lookup(key3, 0, key3.length, hashMapResult); assertTrue(joinResult == JoinUtil.JoinResult.NOMATCH); assertTrue(!hashMapResult.hasRows()); } @Test public void testFullMap() throws Exception { random = new Random(200001); // Make sure the map does not expand; should be able to find space. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap(false,CAPACITY, 1f, WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); for (int i = 0; i < CAPACITY; i++) { byte[] key; while (true) { key = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key); if (!verifyTable.contains(key)) { // Unique keys for this test. break; } } byte[] value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); // verifyTable.verify(map); } verifyTable.verify(map); byte[] anotherKey; while (true) { anotherKey = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(anotherKey); if (!verifyTable.contains(anotherKey)) { // Unique keys for this test. break; } } VectorMapJoinHashMapResult hashMapResult = map.createHashMapResult(); JoinUtil.JoinResult joinResult = map.lookup(anotherKey, 0, anotherKey.length, hashMapResult); assertTrue(joinResult == JoinUtil.JoinResult.NOMATCH); } @Test public void testExpand() throws Exception { random = new Random(99221); // Start with capacity 1; make sure we expand on every put. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap(false,1, 0.0000001f, WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); for (int i = 0; i < 18; ++i) { byte[] key; while (true) { key = new byte[random.nextInt(MAX_KEY_LENGTH)]; random.nextBytes(key); if (!verifyTable.contains(key)) { // Unique keys for this test. break; } } byte[] value = new byte[random.nextInt(MAX_VALUE_LENGTH)]; random.nextBytes(value); map.testPutRow(key, value); verifyTable.add(key, value); // verifyTable.verify(map); } verifyTable.verify(map); // assertEquals(1 << 18, map.getCapacity()); } public void addAndVerifyMultipleKeyMultipleValue(int keyCount, VectorMapJoinFastMultiKeyHashMap map, VerifyFastBytesHashMap verifyTable) throws HiveException, IOException { addAndVerifyMultipleKeyMultipleValue(keyCount, map, verifyTable, MAX_KEY_LENGTH, -1); } public void addAndVerifyMultipleKeyMultipleValue(int keyCount, VectorMapJoinFastMultiKeyHashMap map, VerifyFastBytesHashMap verifyTable, int maxKeyLength, int fixedValueLength) throws HiveException, IOException { for (int i = 0; i < keyCount; i++) { byte[] value; if (fixedValueLength == -1) { value = new byte[generateLargeCount() - 1]; } else { value = new byte[fixedValueLength]; } random.nextBytes(value); // Add a new key or add a value to an existing key? if (random.nextBoolean() || verifyTable.getCount() == 0) { byte[] key; while (true) { key = new byte[random.nextInt(maxKeyLength)]; random.nextBytes(key); if (!verifyTable.contains(key)) { // Unique keys for this test. break; } } map.testPutRow(key, value); verifyTable.add(key, value); // verifyTable.verify(map); } else { byte[] randomExistingKey = verifyTable.addRandomExisting(value, random); map.testPutRow(randomExistingKey, value); // verifyTable.verify(map); } } verifyTable.verify(map); } @Test public void testMultipleKeysMultipleValue() throws Exception { random = new Random(9332); // Use a large capacity that doesn't require expansion, yet. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,LARGE_CAPACITY, LOAD_FACTOR, LARGE_WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); int keyCount = 1000; addAndVerifyMultipleKeyMultipleValue(keyCount, map, verifyTable); } @Test public void testLargeAndExpand() throws Exception { random = new Random(21111); // Use a large capacity that doesn't require expansion, yet. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,MODERATE_CAPACITY, LOAD_FACTOR, MODERATE_WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); int keyCount = 1000; addAndVerifyMultipleKeyMultipleValue(keyCount, map, verifyTable); } @Test public void testReallyBig() throws Exception { random = new Random(42662); // Use a large capacity that doesn't require expansion, yet. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false,LARGE_CAPACITY, LOAD_FACTOR, MODERATE_WB_SIZE, -1); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); int keyCount = 1000000; addAndVerifyMultipleKeyMultipleValue(keyCount, map, verifyTable); } /* // Can't seem to get mvn to give enough memory to run this successfully. @Test public void testKeyCountLimit() throws Exception { random = new Random(28400); // Use a large capacity that doesn't require expansion, yet. VectorMapJoinFastMultiKeyHashMap map = new VectorMapJoinFastMultiKeyHashMap( false, LARGE_CAPACITY, LOAD_FACTOR, LARGE_WB_SIZE, 10000000); VerifyFastBytesHashMap verifyTable = new VerifyFastBytesHashMap(); int keyCount = Integer.MAX_VALUE; try { addAndVerifyMultipleKeyMultipleValue(keyCount, map, verifyTable, 10, 1); } catch (RuntimeException re) { System.out.println(re.toString()); assertTrue(re.toString().startsWith("Vector MapJoin Bytes Hash Table cannot grow any more")); } } */ }