blob: 8e726d6edbf2258396dd4b90bec415189384557d [file] [log] [blame]
/*
* 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.drill.exec.record;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.drill.exec.vector.AllocationHelper;
import org.apache.drill.exec.vector.ValueVector;
import org.apache.drill.exec.vector.complex.AbstractMapVector;
import org.apache.drill.exec.vector.complex.AbstractRepeatedMapVector;
import org.apache.drill.common.map.CaseInsensitiveMap;
import com.google.common.annotations.VisibleForTesting;
/**
* Prototype mechanism to allocate vectors based on expected
* data sizes. This version uses a name-based map of fields
* to sizes. Better to represent the batch structurally and
* simply iterate over the schema rather than doing a per-field
* lookup. But, the mechanisms needed to do the efficient solution
* don't exist yet.
* <p>
* The element count is a float because it might be fractional.
* If every tenth array has an element, then the count per array
* is 0.1.
*/
public class VectorInitializer {
@VisibleForTesting
public static class AllocationHint {
public final int entryWidth;
public final float elementCount;
private AllocationHint(int width, float elements) {
entryWidth = width;
elementCount = elements;
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder()
.append("{");
String sep = "";
if (entryWidth > 0) {
buf.append("width=")
.append(entryWidth);
sep = ", ";
}
if (elementCount > 0) {
buf.append(sep)
.append("elements=")
.append(elementCount);
}
buf.append("}");
return buf.toString();
}
}
private Map<String, AllocationHint> hints = CaseInsensitiveMap.newHashMap();
public void variableWidth(String name, int width) {
hints.put(name, new AllocationHint(width, 1));
}
public void fixedWidthArray(String name, float elements) {
hints.put(name, new AllocationHint(0, elements));
}
public void variableWidthArray(String name, float width, float elements) {
hints.put(name, new AllocationHint((int) Math.ceil(width), elements));
}
public AllocationHint hint(String name) {
return hints.get(name);
}
public void allocateBatch(VectorAccessible va, int recordCount) {
for (VectorWrapper<?> w: va) {
allocateVector(w.getValueVector(), "", recordCount);
}
}
public void allocateVectors(List<ValueVector> valueVectors, int recordCount) {
for (ValueVector v : valueVectors) {
allocateVector(v, v.getField().getName(), recordCount);
}
}
public void allocateVector(ValueVector vector, String prefix, int recordCount) {
String key = prefix + vector.getField().getName();
AllocationHint hint = hints.get(key);
if (vector instanceof AbstractMapVector) {
allocateMap((AbstractMapVector) vector, prefix, recordCount, hint);
} else {
allocateVector(vector, recordCount, hint);
}
// Set<BufferLedger> ledgers = new HashSet<>();
// vector.collectLedgers(ledgers);
// int size = 0;
// for (BufferLedger ledger : ledgers) {
// size += ledger.getAccountedSize();
// }
// System.out.println(key + ": " + vector.getField().toString() +
// " " +
// ((hint == null) ? "no hint" : hint.toString()) +
// ", " + size);
}
public void allocateVector(ValueVector vector, int recordCount, AllocationHint hint) {
if (hint == null) {
// Use hard-coded values. Same as ScanBatch
AllocationHelper.allocate(vector, recordCount, 50, 10);
} else {
AllocationHelper.allocate(vector, recordCount, hint.entryWidth, hint.elementCount);
}
}
private void allocateMap(AbstractMapVector map, String prefix, int recordCount, AllocationHint hint) {
if (map instanceof AbstractRepeatedMapVector) {
((AbstractRepeatedMapVector) map).allocateOffsetsNew(recordCount);
if (hint == null) {
recordCount *= 10;
} else {
recordCount *= Math.round(hint.elementCount);
}
}
prefix += map.getField().getName() + ".";
for (ValueVector vector : map) {
allocateVector(vector, prefix, recordCount);
}
}
@Override
public String toString() {
StringBuilder buf = new StringBuilder();
buf.append("[" + getClass().getSimpleName())
.append(" ");
boolean first = true;
for (Entry<String, AllocationHint>entry : hints.entrySet()) {
if (! first) {
buf.append(", ");
}
first = false;
buf.append("[")
.append(entry.getKey())
.append(" ")
.append(entry.getValue().toString())
.append("]");
}
buf.append("]");
return buf.toString();
}
}