io.deephaven.engine.table.impl.by.OperatorAggregationStateManagerOpenAddressedBase Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deephaven-engine-table Show documentation
Show all versions of deephaven-engine-table Show documentation
Engine Table: Implementation and closely-coupled utilities
/**
* Copyright (c) 2016-2022 Deephaven Data Labs and Patent Pending
*/
package io.deephaven.engine.table.impl.by;
import io.deephaven.base.verify.Require;
import io.deephaven.chunk.Chunk;
import io.deephaven.chunk.attributes.Values;
import io.deephaven.engine.rowset.RowSequence;
import io.deephaven.engine.table.*;
import io.deephaven.engine.table.impl.sources.InMemoryColumnSource;
import io.deephaven.engine.table.impl.util.TypedHasherUtil.BuildOrProbeContext.BuildContext;
import static io.deephaven.engine.table.impl.util.TypedHasherUtil.getKeyChunks;
public abstract class OperatorAggregationStateManagerOpenAddressedBase
implements OperatorAggregationStateManager {
public static final int CHUNK_SIZE = ChunkedOperatorAggregationHelper.CHUNK_SIZE;
private static final long MAX_TABLE_SIZE = 1 << 30; // maximum array size
// the number of slots in our table
protected int tableSize;
protected long numEntries = 0;
// the table will be rehashed to a load factor of targetLoadFactor if our loadFactor exceeds maximumLoadFactor
// or if it falls below minimum load factor we will instead contract the table
private final double maximumLoadFactor;
// the keys for our hash entries
protected final ColumnSource[] mainKeySources;
protected OperatorAggregationStateManagerOpenAddressedBase(ColumnSource>[] tableKeySources, int tableSize,
double maximumLoadFactor) {
this.tableSize = tableSize;
Require.leq(tableSize, "tableSize", MAX_TABLE_SIZE);
Require.gtZero(tableSize, "tableSize");
Require.eq(Integer.bitCount(tableSize), "Integer.bitCount(tableSize)", 1);
Require.inRange(maximumLoadFactor, 0.0, 0.95, "maximumLoadFactor");
mainKeySources = new ColumnSource[tableKeySources.length];
for (int ii = 0; ii < tableKeySources.length; ++ii) {
mainKeySources[ii] = InMemoryColumnSource.getImmutableMemoryColumnSource(tableSize,
tableKeySources[ii].getType(), tableKeySources[ii].getComponentType());
}
this.maximumLoadFactor = maximumLoadFactor;
}
@Override
public final int maxTableSize() {
return Math.toIntExact(MAX_TABLE_SIZE);
}
protected abstract void build(RowSequence rowSequence, Chunk[] sourceKeyChunks);
BuildContext makeBuildContext(ColumnSource>[] buildSources, long maxSize) {
return new BuildContext(buildSources, (int) Math.min(CHUNK_SIZE, maxSize));
}
protected abstract void onNextChunk(int nextChunkSize);
protected void buildTable(
final BuildContext bc,
final RowSequence buildRows,
final ColumnSource>[] buildSources) {
try (final RowSequence.Iterator rsIt = buildRows.getRowSequenceIterator()) {
// noinspection unchecked
final Chunk[] sourceKeyChunks = new Chunk[buildSources.length];
while (rsIt.hasMore()) {
final RowSequence chunkOk = rsIt.getNextRowSequenceWithLength(bc.chunkSize);
final int nextChunkSize = chunkOk.intSize();
onNextChunk(nextChunkSize);
doRehash(nextChunkSize);
getKeyChunks(buildSources, bc.getContexts, sourceKeyChunks, chunkOk);
build(chunkOk, sourceKeyChunks);
bc.resetSharedContexts();
}
}
}
public void doRehash(int nextChunkSize) {
final int oldSize = tableSize;
while (rehashRequired(nextChunkSize)) {
tableSize *= 2;
if (tableSize < 0 || tableSize > MAX_TABLE_SIZE) {
throw new UnsupportedOperationException("Hash table exceeds maximum size!");
}
}
if (tableSize > oldSize) {
rehashInternalFull(oldSize);
}
}
protected abstract void rehashInternalFull(int oldSize);
public boolean rehashRequired(int nextChunkSize) {
return (numEntries + nextChunkSize) > (tableSize * maximumLoadFactor);
}
protected int hashToTableLocation(int hash) {
return hash & (tableSize - 1);
}
@Override
abstract public int findPositionForKey(Object key);
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy