From 6302b68068749b874cbaa2642188c14d5d461132 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 24 Aug 2022 15:34:08 -0700 Subject: [PATCH 01/25] use RowSetBuilderRandom instead of RowSet.insert calls --- .../impl/by/PartitionByChunkedOperator.java | 166 ++++++++++-------- 1 file changed, 91 insertions(+), 75 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 892f1f5fd97..9817453914a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -17,11 +17,7 @@ import io.deephaven.chunk.attributes.Values; import io.deephaven.engine.liveness.LivenessReferent; import io.deephaven.engine.liveness.LivenessScopeStack; -import io.deephaven.engine.rowset.RowSequence; -import io.deephaven.engine.rowset.RowSet; -import io.deephaven.engine.rowset.RowSetFactory; -import io.deephaven.engine.rowset.RowSetShiftData; -import io.deephaven.engine.rowset.WritableRowSet; +import io.deephaven.engine.rowset.*; import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; import io.deephaven.engine.rowset.chunkattributes.RowKeys; import io.deephaven.engine.rowset.impl.AdaptiveOrderedLongSetBuilderRandom; @@ -62,20 +58,20 @@ public final class PartitionByChunkedOperator implements IterativeChunkedAggrega * longer live or the aggregation update listener was no longer live. Should be used for assignment and reference * equality tests, only. */ - private static final WritableRowSet NONEXISTENT_TABLE_ROW_SET = RowSetFactory.empty(); + private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER = RowSetFactory.builderRandom(); /** * Sentinel value for the shift builder belonging to a table that was never created because either the result table * was no longer live or the aggregation update listener was no longer live. Should be used for assignment and * reference equality tests, only. */ private static final RowSetShiftData.SmartCoalescingBuilder NONEXISTENT_TABLE_SHIFT_BUILDER = - new RowSetShiftData.SmartCoalescingBuilder(NONEXISTENT_TABLE_ROW_SET); + new RowSetShiftData.SmartCoalescingBuilder(RowSetFactory.empty()); /** * Sentinel value for a table that was never created because either the result table was no longer live or the * aggregation update listener was no longer live. Should be used for assignment and reference equality tests, only. */ private static final QueryTable NONEXISTENT_TABLE = - new QueryTable(NONEXISTENT_TABLE_ROW_SET.toTracking(), Collections.emptyMap()); + new QueryTable(RowSetFactory.empty().toTracking(), Collections.emptyMap()); // endregion nonexistent table sentinels @@ -90,9 +86,14 @@ public interface AttributeCopier { private final String callSite; private final ObjectArraySource tables; - private final ObjectArraySource addedRowSets; - private final ObjectArraySource removedRowSets; - private final ObjectArraySource modifiedRowSets; +// private final ObjectArraySource addedRowSetBuilders; +// private final ObjectArraySource removedRowSetBuilders; +// private final ObjectArraySource modifiedRowSetBuilders; + + private final ObjectArraySource addedRowSetBuilders; + private final ObjectArraySource removedRowSetBuilders; + private final ObjectArraySource modifiedRowSetBuilders; + private final ObjectArraySource shiftDataBuilders; private final ModifiedColumnSet resultModifiedColumnSet; private final ModifiedColumnSet.Transformer upstreamToResultTransformer; @@ -143,7 +144,7 @@ public interface AttributeCopier { callSite = QueryPerformanceRecorder.getCallerLine(); tables = new ObjectArraySource<>(QueryTable.class); - addedRowSets = new ObjectArraySource<>(WritableRowSet.class); + addedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); // Note: Sub-tables always share their ColumnSource map with the parent table, so they can all use this result // MCS. @@ -158,8 +159,8 @@ public interface AttributeCopier { } if (parentTable.isRefreshing()) { - removedRowSets = new ObjectArraySource<>(WritableRowSet.class); - modifiedRowSets = new ObjectArraySource<>(WritableRowSet.class); + removedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + modifiedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); shiftDataBuilders = new ObjectArraySource<>(RowSetShiftData.SmartCoalescingBuilder.class); final Set keyColumnNameSet = Arrays.stream(keyColumnNames).collect(Collectors.toSet()); @@ -177,8 +178,8 @@ public interface AttributeCopier { retainedResultColumnNames, retainedResultModifiedColumnSets); } else { - removedRowSets = null; - modifiedRowSets = null; + removedRowSetBuilders = null; + modifiedRowSetBuilders = null; shiftDataBuilders = null; upstreamToResultTransformer = null; } @@ -199,7 +200,7 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; - accumulateToRowSet(addedRowSets, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToRowSet(addedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); } @@ -315,7 +316,7 @@ public boolean addChunk(final SingletonContext singletonContext, final int chunk @Override public boolean addRowSet(SingletonContext context, RowSet rowSet, long destination) { - accumulateToRowSet(addedRowSets, rowSet, destination); + accumulateToRowSet(addedRowSetBuilders, rowSet, destination); if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); } @@ -330,7 +331,7 @@ public boolean removeChunk(final SingletonContext singletonContext, final int ch Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); // noinspection unchecked final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; - accumulateToRowSet(removedRowSets, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToRowSet(removedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); stepUpdatedDestinations.insert(destination); return false; } @@ -367,39 +368,46 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long } // noinspection unchecked final LongChunk rowKeysAsOrdered = (LongChunk) rowKeys; - accumulateToRowSet(modifiedRowSets, rowKeysAsOrdered, 0, rowKeys.size(), destination); + accumulateToRowSet(modifiedRowSetBuilders, rowKeysAsOrdered, 0, rowKeys.size(), destination); stepUpdatedDestinations.insert(destination); return false; } - private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { - final WritableRowSet rowSet = rowSetColumn.getUnsafe(destination); - if (rowSet == NONEXISTENT_TABLE_ROW_SET) { + final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } - if (rowSet == null) { - rowSetColumn.set(destination, - new WritableRowSetImpl(OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false))); + if (builder == null) { + final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); + OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s,e) -> { + newBuilder.addRange(s,e); + return true; + }); + rowSetColumn.set(destination, newBuilder); return; } - rowSet.insert(rowKeysToAdd, start, length); + OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s,e) -> { + builder.addRange(s,e); + return true; + }); } - private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, @NotNull final RowSet rowSetToAdd, final long destination) { - final WritableRowSet rowSet = rowSetColumn.getUnsafe(destination); - if (rowSet == NONEXISTENT_TABLE_ROW_SET) { + final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } - if (rowSet == null) { - final WritableRowSet currentRowSet = RowSetFactory.empty(); - currentRowSet.insert(rowSetToAdd); - rowSetColumn.set(destination, currentRowSet); + if (builder == null) { + final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); + newBuilder.addRowSet(rowSetToAdd); + rowSetColumn.set(destination, newBuilder); return; } - rowSet.insert(rowSetToAdd); + builder.addRowSet(rowSetToAdd); } private boolean appendShifts(@NotNull final LongChunk preShiftRowKeys, @@ -411,12 +419,18 @@ private boolean appendShifts(@NotNull final LongChunk preShif } if (builder == null) { final RowSet tableRowSet = tables.getUnsafe(destination).getRowSet(); - final RowSet removedRowSet = removedRowSets.getUnsafe(destination); + final RowSetBuilderRandom removedRowSetBuilder = removedRowSetBuilders.getUnsafe(destination); final RowSet preShiftKeys; - if (removedRowSet == null) { + if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); } else { - preShiftKeys = tableRowSet.minus(removedRowSet); + // keep this as a valid builder + try (final RowSet rs = removedRowSetBuilder.build()) { + preShiftKeys = tableRowSet.minus(rs); + RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); + newBuilder.addRowSet(rs); + removedRowSetBuilders.set(destination, newBuilder); + } } shiftDataBuilders.set(destination, builder = new RowSetShiftData.SmartCoalescingBuilder(preShiftKeys)); } @@ -446,10 +460,10 @@ private boolean appendShifts(@NotNull final LongChunk preShif @Override public void ensureCapacity(final long tableSize) { tables.ensureCapacity(tableSize); - addedRowSets.ensureCapacity(tableSize); + addedRowSetBuilders.ensureCapacity(tableSize); if (parentTable.isRefreshing()) { - removedRowSets.ensureCapacity(tableSize); - modifiedRowSets.ensureCapacity(tableSize); + removedRowSetBuilders.ensureCapacity(tableSize); + modifiedRowSetBuilders.ensureCapacity(tableSize); shiftDataBuilders.ensureCapacity(tableSize); } } @@ -480,14 +494,14 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final WritableObjectChunk tablesBackingChunk = tablesResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = + final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); while (initialDestinationsIterator.hasMore()) { final long firstSliceDestination = initialDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSets.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence initialDestinationsSlice = @@ -582,7 +596,7 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedRowSetsResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final RowSequence.Iterator resurrectedDestinationsIterator = resurrectedDestinations.getRowSequenceIterator()) { @@ -591,14 +605,14 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = + final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); while (resurrectedDestinationsIterator.hasMore()) { final long firstSliceDestination = resurrectedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSets.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence resurrectedDestinationsSlice = resurrectedDestinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); @@ -660,13 +674,13 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final WritableObjectChunk tablesBackingChunk = tablesResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = + final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = + final WritableObjectChunk removedRowSetsBackingChunk = allowCreation ? null : removedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk modifiedRowSetsBackingChunk = + final WritableObjectChunk modifiedRowSetsBackingChunk = allowCreation ? null : modifiedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked final WritableObjectChunk shiftDataBuildersBackingChunk = @@ -676,11 +690,11 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final long firstSliceDestination = newDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSets.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); if (!allowCreation) { - removedRowSets.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); - modifiedRowSets.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, + modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, firstSliceDestination); shiftDataBuilders.resetWritableChunkToBackingStore(shiftDataBuildersResettableChunk, firstSliceDestination); @@ -700,9 +714,9 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations } else { // We will never try to create this table again, or accumulate further state for it. tablesBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE); - addedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET); - removedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET); - modifiedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET); + addedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); + removedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); + modifiedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); shiftDataBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_SHIFT_BUILDER); } }); @@ -734,7 +748,7 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = + final ResettableWritableObjectChunk removedRowSetsResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { // Destinations that were completely removed can't have any additions, modifications, or shifts. @@ -742,14 +756,14 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = + final WritableObjectChunk removedRowSetsBackingChunk = removedRowSetsResettableChunk.asWritableObjectChunk(); while (removedDestinationsIterator.hasMore()) { final long firstSliceDestination = removedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - removedRowSets.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence removedDestinationsSlice = removedDestinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); @@ -789,11 +803,11 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedRowSetsResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = + final ResettableWritableObjectChunk removedRowSetsResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); @@ -803,13 +817,13 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = + final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = + final WritableObjectChunk removedRowSetsBackingChunk = removedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk modifiedRowSetsBackingChunk = + final WritableObjectChunk modifiedRowSetsBackingChunk = modifiedRowSetsResettableChunk.asWritableObjectChunk(); // noinspection unchecked final WritableObjectChunk shiftDataBuildersBackingChunk = @@ -820,9 +834,9 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); // The (valid) assumption is that the other write-through resets will address the same range. - addedRowSets.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); - removedRowSets.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); - modifiedRowSets.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); + modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, firstSliceDestination); shiftDataBuilders.resetWritableChunkToBackingStore(shiftDataBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; @@ -872,14 +886,16 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m } private static WritableRowSet extractAndClearRowSet( - @NotNull final WritableObjectChunk rowSetChunk, + @NotNull final WritableObjectChunk rowSetChunk, final int offset) { - final WritableRowSet rowSet = rowSetChunk.get(offset); - Assert.neq(rowSet, "rowSet", NONEXISTENT_TABLE_ROW_SET, "NONEXISTENT_TABLE_ROW_SET"); - if (rowSet != null) { + final RowSetBuilderRandom builder = rowSetChunk.get(offset); + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER, "NONEXISTENT_TABLE_ROW_SET_BUILDER"); + if (builder != null) { + final WritableRowSet rowSet = builder.build(); rowSetChunk.set(offset, null); + return rowSet; } - return rowSet; + return null; } private static RowSet nullToEmpty(@Nullable final RowSet rowSet) { From 779898e428507852148bee435f70dac2f0385e47 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 24 Aug 2022 15:57:45 -0700 Subject: [PATCH 02/25] PT tests passing, spotless applied --- .../impl/by/PartitionByChunkedOperator.java | 56 ++++++++++++------- 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 9817453914a..da6b5060206 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -54,24 +54,30 @@ public final class PartitionByChunkedOperator implements IterativeChunkedAggrega // region nonexistent table sentinels /** - * Sentinel value for the row set belonging to a table that was never created because either the result table was no - * longer live or the aggregation update listener was no longer live. Should be used for assignment and reference - * equality tests, only. + * Sentinel value for the row set builder belonging to a table that was never created because either the result + * table was no longer live or the aggregation update listener was no longer live. Should be used for assignment and + * reference equality tests, only. */ private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER = RowSetFactory.builderRandom(); + + /** + * Helper value for the following sentinel values but not used directly for comparison + */ + private static final WritableRowSet NONEXISTENT_TABLE_ROW_SET = RowSetFactory.empty(); + /** * Sentinel value for the shift builder belonging to a table that was never created because either the result table * was no longer live or the aggregation update listener was no longer live. Should be used for assignment and * reference equality tests, only. */ private static final RowSetShiftData.SmartCoalescingBuilder NONEXISTENT_TABLE_SHIFT_BUILDER = - new RowSetShiftData.SmartCoalescingBuilder(RowSetFactory.empty()); + new RowSetShiftData.SmartCoalescingBuilder(NONEXISTENT_TABLE_ROW_SET); /** * Sentinel value for a table that was never created because either the result table was no longer live or the * aggregation update listener was no longer live. Should be used for assignment and reference equality tests, only. */ private static final QueryTable NONEXISTENT_TABLE = - new QueryTable(RowSetFactory.empty().toTracking(), Collections.emptyMap()); + new QueryTable(NONEXISTENT_TABLE_ROW_SET.toTracking(), Collections.emptyMap()); // endregion nonexistent table sentinels @@ -86,10 +92,6 @@ public interface AttributeCopier { private final String callSite; private final ObjectArraySource tables; -// private final ObjectArraySource addedRowSetBuilders; -// private final ObjectArraySource removedRowSetBuilders; -// private final ObjectArraySource modifiedRowSetBuilders; - private final ObjectArraySource addedRowSetBuilders; private final ObjectArraySource removedRowSetBuilders; private final ObjectArraySource modifiedRowSetBuilders; @@ -381,16 +383,18 @@ private static void accumulateToRowSet(@NotNull final ObjectArraySource { - newBuilder.addRange(s,e); + OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s, e) -> { + newBuilder.addRange(s, e); return true; }); rowSetColumn.set(destination, newBuilder); return; } - OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s,e) -> { - builder.addRange(s,e); + // add the keys to the stored builder + OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s, e) -> { + builder.addRange(s, e); return true; }); } @@ -402,11 +406,13 @@ private static void accumulateToRowSet(@NotNull final ObjectArraySource preShif if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); } else { - // keep this as a valid builder + // we want to keep the builder in `removedRowSetBuilders` ready for a call to `extractAndClearRowSet` so + // we remake the builder after this call try (final RowSet rs = removedRowSetBuilder.build()) { preShiftKeys = tableRowSet.minus(rs); RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); @@ -501,7 +508,8 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final long firstSliceDestination = initialDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence initialDestinationsSlice = @@ -612,7 +620,8 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre final long firstSliceDestination = resurrectedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence resurrectedDestinationsSlice = resurrectedDestinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); @@ -690,7 +699,8 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final long firstSliceDestination = newDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + firstSliceDestination); if (!allowCreation) { removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); @@ -763,7 +773,8 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re final long firstSliceDestination = removedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence removedDestinationsSlice = removedDestinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); @@ -834,9 +845,12 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); // The (valid) assumption is that the other write-through resets will address the same range. - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); - removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); - modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, firstSliceDestination); + addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + firstSliceDestination); + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + firstSliceDestination); + modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, + firstSliceDestination); shiftDataBuilders.resetWritableChunkToBackingStore(shiftDataBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; From a28e7589144e6c5bbd2814b915ab398397cafe2f Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Thu, 25 Aug 2022 08:35:05 -0700 Subject: [PATCH 03/25] wip --- .../table/impl/by/PartitionByChunkedOperator.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index da6b5060206..423feaadb29 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -382,21 +382,17 @@ private static void accumulateToRowSet(@NotNull final ObjectArraySource sliced = rowKeysToAdd.slice(start, length); if (builder == null) { // create (and store) a new builder, fill with these keys final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); - OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s, e) -> { - newBuilder.addRange(s, e); - return true; - }); + newBuilder.addRowKeysChunk(sliced); rowSetColumn.set(destination, newBuilder); return; } // add the keys to the stored builder - OrderedLongSet.fromChunk(rowKeysToAdd, start, length, false).ixForEachLongRange((s, e) -> { - builder.addRange(s, e); - return true; - }); + builder.addRowKeysChunk(sliced); } private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, From 9cd408d13cc3223772cfc43b92882383525c00c9 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 14 Sep 2022 09:38:56 -0700 Subject: [PATCH 04/25] updated PT to use builders --- .../impl/by/PartitionByChunkedOperator.java | 289 +++++++++++------- 1 file changed, 184 insertions(+), 105 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 423feaadb29..b2a538829e4 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -21,7 +21,6 @@ import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; import io.deephaven.engine.rowset.chunkattributes.RowKeys; import io.deephaven.engine.rowset.impl.AdaptiveOrderedLongSetBuilderRandom; -import io.deephaven.engine.rowset.impl.OrderedLongSet; import io.deephaven.engine.rowset.impl.WritableRowSetImpl; import io.deephaven.engine.table.ColumnDefinition; import io.deephaven.engine.table.ColumnSource; @@ -58,7 +57,8 @@ public final class PartitionByChunkedOperator implements IterativeChunkedAggrega * table was no longer live or the aggregation update listener was no longer live. Should be used for assignment and * reference equality tests, only. */ - private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER = RowSetFactory.builderRandom(); + private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM = RowSetFactory.builderRandom(); + private static final RowSetBuilderSequential NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL = RowSetFactory.builderSequential(); /** * Helper value for the following sentinel values but not used directly for comparison @@ -92,6 +92,7 @@ public interface AttributeCopier { private final String callSite; private final ObjectArraySource tables; + private final ObjectArraySource addedRowSetBuildersSequential; private final ObjectArraySource addedRowSetBuilders; private final ObjectArraySource removedRowSetBuilders; private final ObjectArraySource modifiedRowSetBuilders; @@ -100,6 +101,8 @@ public interface AttributeCopier { private final ModifiedColumnSet resultModifiedColumnSet; private final ModifiedColumnSet.Transformer upstreamToResultTransformer; + private volatile boolean initialized; + private volatile Table resultTable; private volatile LivenessReferent aggregationUpdateListener; @@ -136,16 +139,18 @@ public interface AttributeCopier { * @param keyColumnNames The key columns */ PartitionByChunkedOperator(@NotNull final QueryTable unadjustedParentTable, - @NotNull final QueryTable parentTable, - @NotNull final String resultName, - @NotNull final AttributeCopier attributeCopier, - @NotNull final String... keyColumnNames) { + @NotNull final QueryTable parentTable, + @NotNull final String resultName, + @NotNull final AttributeCopier attributeCopier, + @NotNull final String... keyColumnNames) { this.parentTable = parentTable; this.resultName = resultName; + this.initialized = false; callSite = QueryPerformanceRecorder.getCallerLine(); tables = new ObjectArraySource<>(QueryTable.class); + addedRowSetBuildersSequential = new ObjectArraySource<>(RowSetBuilderSequential.class); addedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); // Note: Sub-tables always share their ColumnSource map with the parent table, so they can all use this result @@ -189,9 +194,9 @@ public interface AttributeCopier { @Override public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); final AdaptiveOrderedLongSetBuilderRandom chunkDestinationsBuilder = stepUpdatedDestinations == null ? null : new AdaptiveOrderedLongSetBuilderRandom(); @@ -202,14 +207,18 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); final AdaptiveOrderedLongSetBuilderRandom chunkDestinationsBuilder = new AdaptiveOrderedLongSetBuilderRandom(); @@ -230,32 +239,32 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public void shiftChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); @@ -271,16 +280,16 @@ public void shiftChunk(final BucketedContext bucketedContext, final Chunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { if (!stepValuesModified) { return; } @@ -293,23 +302,27 @@ public void modifyRowKeys(final BucketedContext context, final int startPosition = startPositions.get(di); final int runLength = length.get(di); final long destination = destinations.get(startPosition); - accumulateToRowSet(modifiedRowSetBuilders, inputRowKeysAsOrdered, startPosition, runLength, destination); + accumulateToBuilderRandom(modifiedRowSetBuilders, inputRowKeysAsOrdered, startPosition, runLength, destination); chunkDestinationsBuilder.addKey(destination); } try (final RowSet chunkUpdatedDestinations = - new WritableRowSetImpl(chunkDestinationsBuilder.getOrderedLongSet())) { + new WritableRowSetImpl(chunkDestinationsBuilder.getOrderedLongSet())) { stepUpdatedDestinations.insert(chunkUpdatedDestinations); } } @Override public boolean addChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); // noinspection unchecked final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; - accumulateToRowSet(addedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); + if (!initialized) { + accumulateToBuilderSequential(addedRowSetBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, destination); + } else { + accumulateToBuilderRandom(addedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); + } if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); } @@ -318,7 +331,11 @@ public boolean addChunk(final SingletonContext singletonContext, final int chunk @Override public boolean addRowSet(SingletonContext context, RowSet rowSet, long destination) { - accumulateToRowSet(addedRowSetBuilders, rowSet, destination); + if (!initialized) { + accumulateToBuilderSequential(addedRowSetBuildersSequential, rowSet, destination); + } else { + accumulateToBuilderRandom(addedRowSetBuilders, rowSet, destination); + } if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); } @@ -327,32 +344,32 @@ public boolean addRowSet(SingletonContext context, RowSet rowSet, long destinati @Override public boolean removeChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); // noinspection unchecked final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; - accumulateToRowSet(removedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToBuilderRandom(removedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); stepUpdatedDestinations.insert(destination); return false; } @Override public boolean modifyChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk previousValues, final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk previousValues, final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public boolean shiftChunk(final SingletonContext singletonContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); @@ -364,22 +381,60 @@ public boolean shiftChunk(final SingletonContext singletonContext, final Chunk rowKeys, - final long destination) { + final long destination) { if (!stepValuesModified) { return false; } // noinspection unchecked final LongChunk rowKeysAsOrdered = (LongChunk) rowKeys; - accumulateToRowSet(modifiedRowSetBuilders, rowKeysAsOrdered, 0, rowKeys.size(), destination); + accumulateToBuilderRandom(modifiedRowSetBuilders, rowKeysAsOrdered, 0, rowKeys.size(), destination); stepUpdatedDestinations.insert(destination); return false; } - private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final LongChunk rowKeysToAdd, - final int start, final int length, final long destination) { + private static void accumulateToBuilderSequential(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { + final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { + return; + } + // slice the chunk to the start and length + LongChunk sliced = rowKeysToAdd.slice(start, length); + if (builder == null) { + // create (and store) a new builder, fill with these keys + final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); + newBuilder.appendOrderedRowKeysChunk(sliced); + rowSetColumn.set(destination, newBuilder); + return; + } + // add the keys to the stored builder + builder.appendOrderedRowKeysChunk(sliced); + } + + private static void accumulateToBuilderSequential(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final RowSet rowSetToAdd, final long destination) { + final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { + return; + } + if (builder == null) { + // create (and store) a new builder, fill with this rowset + final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); + newBuilder.appendRowSequence(rowSetToAdd); + rowSetColumn.set(destination, newBuilder); + return; + } + // add the rowset to the stored builder + builder.appendRowSequence(rowSetToAdd); + } + + + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { return; } // slice the chunk to the start and length @@ -395,10 +450,10 @@ private static void accumulateToRowSet(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final RowSet rowSetToAdd, final long destination) { + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { return; } if (builder == null) { @@ -413,8 +468,8 @@ private static void accumulateToRowSet(@NotNull final ObjectArraySource preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final int startPosition, final int runLength, final long destination) { + @NotNull final LongChunk postShiftRowKeys, + final int startPosition, final int runLength, final long destination) { RowSetShiftData.SmartCoalescingBuilder builder = shiftDataBuilders.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_SHIFT_BUILDER) { return false; @@ -464,6 +519,9 @@ private boolean appendShifts(@NotNull final LongChunk preShif public void ensureCapacity(final long tableSize) { tables.ensureCapacity(tableSize); addedRowSetBuilders.ensureCapacity(tableSize); + if (!initialized) { + addedRowSetBuildersSequential.ensureCapacity(tableSize); + } if (parentTable.isRefreshing()) { removedRowSetBuilders.ensureCapacity(tableSize); modifiedRowSetBuilders.ensureCapacity(tableSize); @@ -487,24 +545,25 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { // initialization scope, and don't need to do anything special to ensure liveness. final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator initialDestinationsIterator = - initialDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + final RowSequence.Iterator initialDestinationsIterator = + initialDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk tablesBackingChunk = tablesResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = + final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); while (initialDestinationsIterator.hasMore()) { final long firstSliceDestination = initialDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + // use the sequential builders during initialization + addedRowSetBuildersSequential.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; @@ -515,7 +574,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final int backingChunkOffset = Math.toIntExact(destinationToInitialize - firstBackingChunkDestination); final WritableRowSet initialRowSet = - extractAndClearRowSet(addedRowSetsBackingChunk, backingChunkOffset); + extractAndClearBuilderSequential(addedRowSetsBackingChunk, backingChunkOffset); final QueryTable newTable = makeSubTable(initialRowSet); tablesBackingChunk.set(backingChunkOffset, newTable); }); @@ -524,6 +583,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { if (setCallSite) { QueryPerformanceRecorder.clearCallsite(); } + initialized = true; } } } @@ -599,11 +659,11 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator resurrectedDestinationsIterator = - resurrectedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator resurrectedDestinationsIterator = + resurrectedDestinations.getRowSequenceIterator()) { // Destinations that were added can't have any removals, modifications, or shifts. // noinspection unchecked @@ -639,7 +699,7 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre final TableUpdateImpl downstream = new TableUpdateImpl(); - downstream.added = nullToEmpty(extractAndClearRowSet(addedRowSetsBackingChunk, backingChunkOffset)); + downstream.added = nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); downstream.removed = RowSetFactory.empty(); downstream.modified = RowSetFactory.empty(); downstream.shifted = RowSetShiftData.EMPTY; @@ -664,16 +724,16 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final boolean allowCreation = retainedResultTable && retainedAggregationUpdateListener; final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk tablesBackingChunk = @@ -713,16 +773,16 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final int backingChunkOffset = Math.toIntExact(newDestination - firstBackingChunkDestination); if (allowCreation) { final WritableRowSet newRowSet = - extractAndClearRowSet(addedRowSetsBackingChunk, backingChunkOffset); + extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset); final QueryTable newTable = makeSubTable(newRowSet); linkTableReferences(newTable); tablesBackingChunk.set(backingChunkOffset, newTable); } else { // We will never try to create this table again, or accumulate further state for it. tablesBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE); - addedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); - removedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); - modifiedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); + addedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); + removedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); + modifiedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); shiftDataBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_SHIFT_BUILDER); } }); @@ -753,10 +813,10 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { // Destinations that were completely removed can't have any additions, modifications, or shifts. // noinspection unchecked @@ -790,7 +850,7 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re downstream.added = RowSetFactory.empty(); downstream.removed = - nullToEmpty(extractAndClearRowSet(removedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(removedRowSetsBackingChunk, backingChunkOffset)); downstream.modified = RowSetFactory.empty(); downstream.shifted = RowSetShiftData.EMPTY; downstream.modifiedColumnSet = ModifiedColumnSet.EMPTY; @@ -809,23 +869,27 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator modifiedDestinationsIterator = - modifiedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + final ResettableWritableObjectChunk addedRowSetsSequentialResettableChunk = + !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator modifiedDestinationsIterator = + modifiedDestinations.getRowSequenceIterator()) { // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked final WritableObjectChunk addedRowSetsBackingChunk = addedRowSetsResettableChunk.asWritableObjectChunk(); + // noinspection unchecked final WritableObjectChunk removedRowSetsBackingChunk = removedRowSetsResettableChunk.asWritableObjectChunk(); @@ -843,6 +907,7 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m // The (valid) assumption is that the other write-through resets will address the same range. addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, firstSliceDestination); + removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, firstSliceDestination); modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, @@ -866,11 +931,12 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final TableUpdateImpl downstream = new TableUpdateImpl(); - downstream.added = nullToEmpty(extractAndClearRowSet(addedRowSetsBackingChunk, backingChunkOffset)); + downstream.added = nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); + downstream.removed = - nullToEmpty(extractAndClearRowSet(removedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(removedRowSetsBackingChunk, backingChunkOffset)); downstream.modified = stepValuesModified - ? nullToEmpty(extractAndClearRowSet(modifiedRowSetsBackingChunk, backingChunkOffset)) + ? nullToEmpty(extractAndClearBuilderRandom(modifiedRowSetsBackingChunk, backingChunkOffset)) : RowSetFactory.empty(); downstream.shifted = extractAndClearShiftDataBuilder(shiftDataBuildersBackingChunk, backingChunkOffset); @@ -895,11 +961,24 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m } } - private static WritableRowSet extractAndClearRowSet( + private static WritableRowSet extractAndClearBuilderRandom( @NotNull final WritableObjectChunk rowSetChunk, final int offset) { final RowSetBuilderRandom builder = rowSetChunk.get(offset); - Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER, "NONEXISTENT_TABLE_ROW_SET_BUILDER"); + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM, "NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM"); + if (builder != null) { + final WritableRowSet rowSet = builder.build(); + rowSetChunk.set(offset, null); + return rowSet; + } + return null; + } + + private static WritableRowSet extractAndClearBuilderSequential( + @NotNull final WritableObjectChunk rowSetChunk, + final int offset) { + final RowSetBuilderSequential builder = rowSetChunk.get(offset); + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL, "NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL"); if (builder != null) { final WritableRowSet rowSet = builder.build(); rowSetChunk.set(offset, null); From ef8985c367ca8a372e9d1a9d532b4186601f2980 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 14 Sep 2022 10:05:47 -0700 Subject: [PATCH 05/25] minor cleanup --- .../impl/by/PartitionByChunkedOperator.java | 206 +++++++++--------- 1 file changed, 109 insertions(+), 97 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index b2a538829e4..a212e0b7afc 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -53,12 +53,13 @@ public final class PartitionByChunkedOperator implements IterativeChunkedAggrega // region nonexistent table sentinels /** - * Sentinel value for the row set builder belonging to a table that was never created because either the result + * Sentinel value for the row set builders belonging to a table that was never created because either the result * table was no longer live or the aggregation update listener was no longer live. Should be used for assignment and * reference equality tests, only. */ private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM = RowSetFactory.builderRandom(); - private static final RowSetBuilderSequential NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL = RowSetFactory.builderSequential(); + private static final RowSetBuilderSequential NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL = + RowSetFactory.builderSequential(); /** * Helper value for the following sentinel values but not used directly for comparison @@ -139,10 +140,10 @@ public interface AttributeCopier { * @param keyColumnNames The key columns */ PartitionByChunkedOperator(@NotNull final QueryTable unadjustedParentTable, - @NotNull final QueryTable parentTable, - @NotNull final String resultName, - @NotNull final AttributeCopier attributeCopier, - @NotNull final String... keyColumnNames) { + @NotNull final QueryTable parentTable, + @NotNull final String resultName, + @NotNull final AttributeCopier attributeCopier, + @NotNull final String... keyColumnNames) { this.parentTable = parentTable; this.resultName = resultName; this.initialized = false; @@ -194,9 +195,9 @@ public interface AttributeCopier { @Override public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); final AdaptiveOrderedLongSetBuilderRandom chunkDestinationsBuilder = stepUpdatedDestinations == null ? null : new AdaptiveOrderedLongSetBuilderRandom(); @@ -208,9 +209,11 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); final AdaptiveOrderedLongSetBuilderRandom chunkDestinationsBuilder = new AdaptiveOrderedLongSetBuilderRandom(); @@ -239,32 +242,33 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public void shiftChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); @@ -280,16 +284,16 @@ public void shiftChunk(final BucketedContext bucketedContext, final Chunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { if (!stepValuesModified) { return; } @@ -302,24 +306,26 @@ public void modifyRowKeys(final BucketedContext context, final int startPosition = startPositions.get(di); final int runLength = length.get(di); final long destination = destinations.get(startPosition); - accumulateToBuilderRandom(modifiedRowSetBuilders, inputRowKeysAsOrdered, startPosition, runLength, destination); + accumulateToBuilderRandom(modifiedRowSetBuilders, inputRowKeysAsOrdered, startPosition, runLength, + destination); chunkDestinationsBuilder.addKey(destination); } try (final RowSet chunkUpdatedDestinations = - new WritableRowSetImpl(chunkDestinationsBuilder.getOrderedLongSet())) { + new WritableRowSetImpl(chunkDestinationsBuilder.getOrderedLongSet())) { stepUpdatedDestinations.insert(chunkUpdatedDestinations); } } @Override public boolean addChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); // noinspection unchecked final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; if (!initialized) { - accumulateToBuilderSequential(addedRowSetBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToBuilderSequential(addedRowSetBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, + destination); } else { accumulateToBuilderRandom(addedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); } @@ -344,8 +350,8 @@ public boolean addRowSet(SingletonContext context, RowSet rowSet, long destinati @Override public boolean removeChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); // noinspection unchecked @@ -357,19 +363,19 @@ public boolean removeChunk(final SingletonContext singletonContext, final int ch @Override public boolean modifyChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk previousValues, final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk previousValues, final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public boolean shiftChunk(final SingletonContext singletonContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); @@ -381,7 +387,7 @@ public boolean shiftChunk(final SingletonContext singletonContext, final Chunk rowKeys, - final long destination) { + final long destination) { if (!stepValuesModified) { return false; } @@ -392,9 +398,10 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long return false; } - private static void accumulateToBuilderSequential(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final LongChunk rowKeysToAdd, - final int start, final int length, final long destination) { + private static void accumulateToBuilderSequential( + @NotNull final ObjectArraySource rowSetColumn, + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { return; @@ -412,8 +419,9 @@ private static void accumulateToBuilderSequential(@NotNull final ObjectArraySour builder.appendOrderedRowKeysChunk(sliced); } - private static void accumulateToBuilderSequential(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final RowSet rowSetToAdd, final long destination) { + private static void accumulateToBuilderSequential( + @NotNull final ObjectArraySource rowSetColumn, + @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { return; @@ -431,8 +439,8 @@ private static void accumulateToBuilderSequential(@NotNull final ObjectArraySour private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final LongChunk rowKeysToAdd, - final int start, final int length, final long destination) { + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { return; @@ -451,7 +459,7 @@ private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, - @NotNull final RowSet rowSetToAdd, final long destination) { + @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { return; @@ -468,8 +476,8 @@ private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final int startPosition, final int runLength, final long destination) { + @NotNull final LongChunk postShiftRowKeys, + final int startPosition, final int runLength, final long destination) { RowSetShiftData.SmartCoalescingBuilder builder = shiftDataBuilders.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_SHIFT_BUILDER) { return false; @@ -545,11 +553,11 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { // initialization scope, and don't need to do anything special to ensure liveness. final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; - final RowSequence.Iterator initialDestinationsIterator = - initialDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + final RowSequence.Iterator initialDestinationsIterator = + initialDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk tablesBackingChunk = @@ -659,11 +667,11 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator resurrectedDestinationsIterator = - resurrectedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator resurrectedDestinationsIterator = + resurrectedDestinations.getRowSequenceIterator()) { // Destinations that were added can't have any removals, modifications, or shifts. // noinspection unchecked @@ -699,7 +707,8 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre final TableUpdateImpl downstream = new TableUpdateImpl(); - downstream.added = nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); + downstream.added = + nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); downstream.removed = RowSetFactory.empty(); downstream.modified = RowSetFactory.empty(); downstream.shifted = RowSetShiftData.EMPTY; @@ -724,16 +733,16 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final boolean allowCreation = retainedResultTable && retainedAggregationUpdateListener; final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = - allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = + allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk tablesBackingChunk = @@ -813,10 +822,10 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { // Destinations that were completely removed can't have any additions, modifications, or shifts. // noinspection unchecked @@ -869,20 +878,20 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m return; } try (final ResettableWritableObjectChunk tablesResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = - initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; - final ResettableWritableObjectChunk addedRowSetsSequentialResettableChunk = - !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; - - final ResettableWritableObjectChunk removedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator modifiedDestinationsIterator = - modifiedDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedRowSetsResettableChunk = + initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + final ResettableWritableObjectChunk addedRowSetsSequentialResettableChunk = + !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + + final ResettableWritableObjectChunk removedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator modifiedDestinationsIterator = + modifiedDestinations.getRowSequenceIterator()) { // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); @@ -931,7 +940,8 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final TableUpdateImpl downstream = new TableUpdateImpl(); - downstream.added = nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); + downstream.added = + nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); downstream.removed = nullToEmpty(extractAndClearBuilderRandom(removedRowSetsBackingChunk, backingChunkOffset)); @@ -965,7 +975,8 @@ private static WritableRowSet extractAndClearBuilderRandom( @NotNull final WritableObjectChunk rowSetChunk, final int offset) { final RowSetBuilderRandom builder = rowSetChunk.get(offset); - Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM, "NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM"); + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM, + "NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM"); if (builder != null) { final WritableRowSet rowSet = builder.build(); rowSetChunk.set(offset, null); @@ -978,7 +989,8 @@ private static WritableRowSet extractAndClearBuilderSequential( @NotNull final WritableObjectChunk rowSetChunk, final int offset) { final RowSetBuilderSequential builder = rowSetChunk.get(offset); - Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL, "NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL"); + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL, + "NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL"); if (builder != null) { final WritableRowSet rowSet = builder.build(); rowSetChunk.set(offset, null); From d747f0249f97a1c987b78077cc40419ef428e196 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 14 Sep 2022 10:54:02 -0700 Subject: [PATCH 06/25] bugfix, re-scope setter for initialized flag --- .../engine/table/impl/by/PartitionByChunkedOperator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 68cd4c7aaa2..2ebd54ad6ce 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -591,9 +591,9 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { if (setCallSite) { QueryPerformanceRecorder.clearCallsite(); } - initialized = true; } } + initialized = true; } @Override From 903bc6c15e5b4eb5857bea5d3de6d105e5a3ccd7 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 14 Sep 2022 15:07:29 -0700 Subject: [PATCH 07/25] ported Builder improvements --- .../engine/rowset/RowSetBuilderRandom.java | 4 ++ .../rowset/RowSetBuilderSequential.java | 6 +- .../engine/rowset/impl/OrderedLongSet.java | 8 +++ .../impl/OrderedLongSetBuilderSequential.java | 4 +- .../impl/RspBitmapBuilderSequential.java | 66 ++++++++++++++++++- 5 files changed, 84 insertions(+), 4 deletions(-) diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderRandom.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderRandom.java index 45b9ec4802e..8179b1aee68 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderRandom.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderRandom.java @@ -50,6 +50,10 @@ default void addOrderedRowKeysChunk(final LongChunk ch addRowKeysChunk(chunk); } + default void addOrderedRowKeysChunk(final LongChunk chunk, int offset, int length) { + addKeys(new LongChunkIterator(chunk, offset, length)); + } + default void addOrderedRowKeysChunk(final IntChunk chunk) { addRowKeysChunk(chunk); } diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderSequential.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderSequential.java index 157e4f7a8d9..c8d6cd7544c 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderSequential.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/RowSetBuilderSequential.java @@ -43,7 +43,11 @@ default void appendKeys(PrimitiveIterator.OfLong it) { } default void appendOrderedRowKeysChunk(final LongChunk chunk) { - appendKeys(new LongChunkIterator(chunk)); + appendOrderedRowKeysChunk(chunk, 0, chunk.size()); + } + + default void appendOrderedRowKeysChunk(final LongChunk chunk, int offset, int length) { + appendKeys(new LongChunkIterator(chunk, offset, length)); } default void appendRanges(final LongRangeIterator it) { diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSet.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSet.java index 2ebaa672f09..48d9d9ea24e 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSet.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSet.java @@ -3,6 +3,7 @@ */ package io.deephaven.engine.rowset.impl; +import io.deephaven.chunk.util.LongChunkIterator; import io.deephaven.configuration.Configuration; import io.deephaven.engine.rowset.RowSequenceFactory; import io.deephaven.engine.rowset.RowSet; @@ -489,6 +490,13 @@ default void appendOrderedLongSet(final long shiftAmount, final OrderedLongSet i }); } + default void appendOrderedRowKeysChunk(LongChunk chunk, int offset, int length) { + LongChunkIterator it = new LongChunkIterator(chunk, offset, length); + while (it.hasNext()) { + appendKey(it.nextLong()); + } + } + @Override default void accept(final long firstKey, final long lastKey) { appendRange(firstKey, lastKey); diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSetBuilderSequential.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSetBuilderSequential.java index 9869c40feb6..d7c9db247bd 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSetBuilderSequential.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/OrderedLongSetBuilderSequential.java @@ -3,9 +3,9 @@ */ package io.deephaven.engine.rowset.impl; -import io.deephaven.engine.rowset.impl.singlerange.*; -import io.deephaven.engine.rowset.impl.sortedranges.SortedRanges; import io.deephaven.engine.rowset.impl.rsp.RspBitmap; +import io.deephaven.engine.rowset.impl.singlerange.SingleRange; +import io.deephaven.engine.rowset.impl.sortedranges.SortedRanges; import io.deephaven.util.annotations.TestUseOnly; public class OrderedLongSetBuilderSequential extends RspBitmapBuilderSequential { diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/RspBitmapBuilderSequential.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/RspBitmapBuilderSequential.java index 336f5be99ef..f3bff5ab81e 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/RspBitmapBuilderSequential.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/RspBitmapBuilderSequential.java @@ -3,8 +3,10 @@ */ package io.deephaven.engine.rowset.impl; +import io.deephaven.chunk.LongChunk; +import io.deephaven.chunk.util.LongChunkIterator; import io.deephaven.engine.rowset.RowSequence; -import io.deephaven.engine.rowset.impl.OrderedLongSet; +import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; import io.deephaven.engine.rowset.impl.rsp.DisposableRspBitmap; import io.deephaven.engine.rowset.impl.rsp.RspArray; import io.deephaven.engine.rowset.impl.rsp.RspBitmap; @@ -119,6 +121,68 @@ public void appendOrderedLongSet(final long shiftAmount, final OrderedLongSet ix rb.appendShiftedUnsafeNoWriteCheck(shiftAmount, (RspBitmap) ix, acquire); } + @Override + public void appendOrderedRowKeysChunk(LongChunk chunk, int offset, int length) { + if (length == 0) { + return; + } + + if (rb != null) { + appendKeyChunkRb(chunk, offset, length); + } else { + appendKeyChunk(chunk, offset, length); + } + } + + private void appendKeyChunkRb(LongChunk chunk, int offset, int length) { + // flush to the rb before appending + if (pendingStart != -1) { + flushPendingRange(); + } + if (pendingContainerKey != -1) { + flushPendingContainer(); + } + + // single key? + if (length == 1) { + rb.appendUnsafeNoWriteCheck(chunk.get(offset)); + return; + } + + // single range? + final int lastOffsetInclusive = offset + length - 1; + final long first = chunk.get(offset); + final long last = chunk.get(lastOffsetInclusive); + if (last - first + 1 == length) { + rb.appendRangeUnsafeNoWriteCheck(first, last); + return; + } + + rb.addValuesUnsafeNoWriteCheck(chunk, offset, length); + } + + private void appendKeyChunk(LongChunk chunk, int offset, int length) { + // single key? + if (length == 1) { + appendKey(chunk.get(offset)); + return; + } + + // single range? + final int lastOffsetInclusive = offset + length - 1; + final long first = chunk.get(offset); + final long last = chunk.get(lastOffsetInclusive); + if (last - first + 1 == length) { + appendRange(first, last); + return; + } + + final LongChunkIterator it = new LongChunkIterator(chunk, offset, length); + while (it.hasNext()) { + appendKey(it.nextLong()); + } + } + protected void flushPendingRange() { final long pendingStartOnEntry = pendingStart; pendingStart = -1; From c4fd8105f8320a553ff691bc04faac79db97e9a7 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Fri, 16 Sep 2022 09:33:12 -0700 Subject: [PATCH 08/25] PR comments round 1 addressed --- .../impl/by/PartitionByChunkedOperator.java | 166 ++++++++---------- 1 file changed, 77 insertions(+), 89 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 2ebd54ad6ce..18aec8601f5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -57,9 +57,7 @@ public final class PartitionByChunkedOperator implements IterativeChunkedAggrega * table was no longer live or the aggregation update listener was no longer live. Should be used for assignment and * reference equality tests, only. */ - private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM = RowSetFactory.builderRandom(); - private static final RowSetBuilderSequential NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL = - RowSetFactory.builderSequential(); + private static final RowSetBuilderRandom NONEXISTENT_TABLE_ROW_SET_BUILDER = RowSetFactory.builderRandom(); /** * Helper value for the following sentinel values but not used directly for comparison @@ -93,10 +91,10 @@ public interface AttributeCopier { private final String callSite; private final ObjectArraySource tables; - private final ObjectArraySource addedRowSetBuildersSequential; - private final ObjectArraySource addedRowSetBuilders; - private final ObjectArraySource removedRowSetBuilders; - private final ObjectArraySource modifiedRowSetBuilders; + private final ObjectArraySource addedBuildersSequential; + private final ObjectArraySource addedBuilders; + private final ObjectArraySource removedBuilders; + private final ObjectArraySource modifiedBuilders; private final ObjectArraySource shiftDataBuilders; private final ModifiedColumnSet resultModifiedColumnSet; @@ -151,8 +149,8 @@ public interface AttributeCopier { callSite = QueryPerformanceRecorder.getCallerLine(); tables = new ObjectArraySource<>(QueryTable.class); - addedRowSetBuildersSequential = new ObjectArraySource<>(RowSetBuilderSequential.class); - addedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + addedBuildersSequential = new ObjectArraySource<>(RowSetBuilderSequential.class); + addedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); // Note: Sub-tables always share their ColumnSource map with the parent table, so they can all use this result // MCS. @@ -167,8 +165,8 @@ public interface AttributeCopier { } if (parentTable.isRefreshing()) { - removedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); - modifiedRowSetBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + removedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + modifiedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); shiftDataBuilders = new ObjectArraySource<>(RowSetShiftData.SmartCoalescingBuilder.class); final Set keyColumnNameSet = Arrays.stream(keyColumnNames).collect(Collectors.toSet()); @@ -186,8 +184,8 @@ public interface AttributeCopier { retainedResultColumnNames, retainedResultModifiedColumnSets); } else { - removedRowSetBuilders = null; - modifiedRowSetBuilders = null; + removedBuilders = null; + modifiedBuilders = null; shiftDataBuilders = null; upstreamToResultTransformer = null; } @@ -209,10 +207,11 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; if (!initialized) { - accumulateToBuilderSequential(addedRowSetBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, + accumulateToBuilderSequential(addedBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, destination); } else { - accumulateToBuilderRandom(addedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToBuilderRandom(addedBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); } if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); @@ -338,9 +337,9 @@ public boolean addChunk(final SingletonContext singletonContext, final int chunk @Override public boolean addRowSet(SingletonContext context, RowSet rowSet, long destination) { if (!initialized) { - accumulateToBuilderSequential(addedRowSetBuildersSequential, rowSet, destination); + accumulateToBuilderSequential(addedBuildersSequential, rowSet, destination); } else { - accumulateToBuilderRandom(addedRowSetBuilders, rowSet, destination); + accumulateToBuilderRandom(addedBuilders, rowSet, destination); } if (stepUpdatedDestinations != null) { stepUpdatedDestinations.insert(destination); @@ -356,7 +355,7 @@ public boolean removeChunk(final SingletonContext singletonContext, final int ch Assert.neqNull(stepUpdatedDestinations, "stepUpdatedDestinations"); // noinspection unchecked final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; - accumulateToBuilderRandom(removedRowSetBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); + accumulateToBuilderRandom(removedBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); stepUpdatedDestinations.insert(destination); return false; } @@ -393,7 +392,7 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long } // noinspection unchecked final LongChunk rowKeysAsOrdered = (LongChunk) rowKeys; - accumulateToBuilderRandom(modifiedRowSetBuilders, rowKeysAsOrdered, 0, rowKeys.size(), destination); + accumulateToBuilderRandom(modifiedBuilders, rowKeysAsOrdered, 0, rowKeys.size(), destination); stepUpdatedDestinations.insert(destination); return false; } @@ -403,9 +402,6 @@ private static void accumulateToBuilderSequential( @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { - return; - } // slice the chunk to the start and length LongChunk sliced = rowKeysToAdd.slice(start, length); if (builder == null) { @@ -423,9 +419,6 @@ private static void accumulateToBuilderSequential( @NotNull final ObjectArraySource rowSetColumn, @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL) { - return; - } if (builder == null) { // create (and store) a new builder, fill with this rowset final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); @@ -442,7 +435,7 @@ private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowKeysToAdd, final int start, final int length, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } // slice the chunk to the start and length @@ -461,7 +454,7 @@ private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); - if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM) { + if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } if (builder == null) { @@ -484,7 +477,7 @@ private boolean appendShifts(@NotNull final LongChunk preShif } if (builder == null) { final RowSet tableRowSet = tables.getUnsafe(destination).getRowSet(); - final RowSetBuilderRandom removedRowSetBuilder = removedRowSetBuilders.getUnsafe(destination); + final RowSetBuilderRandom removedRowSetBuilder = removedBuilders.getUnsafe(destination); final RowSet preShiftKeys; if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); @@ -495,7 +488,7 @@ private boolean appendShifts(@NotNull final LongChunk preShif preShiftKeys = tableRowSet.minus(rs); RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); newBuilder.addRowSet(rs); - removedRowSetBuilders.set(destination, newBuilder); + removedBuilders.set(destination, newBuilder); } } shiftDataBuilders.set(destination, builder = new RowSetShiftData.SmartCoalescingBuilder(preShiftKeys)); @@ -526,13 +519,13 @@ private boolean appendShifts(@NotNull final LongChunk preShif @Override public void ensureCapacity(final long tableSize) { tables.ensureCapacity(tableSize); - addedRowSetBuilders.ensureCapacity(tableSize); + addedBuilders.ensureCapacity(tableSize); if (!initialized) { - addedRowSetBuildersSequential.ensureCapacity(tableSize); + addedBuildersSequential.ensureCapacity(tableSize); } if (parentTable.isRefreshing()) { - removedRowSetBuilders.ensureCapacity(tableSize); - modifiedRowSetBuilders.ensureCapacity(tableSize); + removedBuilders.ensureCapacity(tableSize); + modifiedBuilders.ensureCapacity(tableSize); shiftDataBuilders.ensureCapacity(tableSize); } } @@ -554,7 +547,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedBuildersResettableChunk = !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; final RowSequence.Iterator initialDestinationsIterator = initialDestinations.getRowSequenceIterator()) { @@ -563,15 +556,15 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final WritableObjectChunk tablesBackingChunk = tablesResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = - addedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); while (initialDestinationsIterator.hasMore()) { final long firstSliceDestination = initialDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); // use the sequential builders during initialization - addedRowSetBuildersSequential.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + addedBuildersSequential.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; @@ -582,7 +575,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final int backingChunkOffset = Math.toIntExact(destinationToInitialize - firstBackingChunkDestination); final WritableRowSet initialRowSet = - extractAndClearBuilderSequential(addedRowSetsBackingChunk, backingChunkOffset); + extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset); final QueryTable newTable = makeSubTable(initialRowSet); tablesBackingChunk.set(backingChunkOffset, newTable); }); @@ -668,7 +661,7 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final RowSequence.Iterator resurrectedDestinationsIterator = resurrectedDestinations.getRowSequenceIterator()) { @@ -677,14 +670,14 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = - addedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); while (resurrectedDestinationsIterator.hasMore()) { final long firstSliceDestination = resurrectedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence resurrectedDestinationsSlice = @@ -708,7 +701,7 @@ private void propagateResurrectedDestinations(@NotNull final RowSequence resurre final TableUpdateImpl downstream = new TableUpdateImpl(); downstream.added = - nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); downstream.removed = RowSetFactory.empty(); downstream.modified = RowSetFactory.empty(); downstream.shifted = RowSetShiftData.EMPTY; @@ -734,11 +727,11 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = + final ResettableWritableObjectChunk removedBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + final ResettableWritableObjectChunk modifiedBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); @@ -748,14 +741,14 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final WritableObjectChunk tablesBackingChunk = tablesResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = - addedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = - allowCreation ? null : removedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk removedBuildersBackingChunk = + allowCreation ? null : removedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk modifiedRowSetsBackingChunk = - allowCreation ? null : modifiedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk modifiedBuildersBackingChunk = + allowCreation ? null : modifiedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked final WritableObjectChunk shiftDataBuildersBackingChunk = allowCreation ? null : shiftDataBuildersResettableChunk.asWritableObjectChunk(); @@ -764,12 +757,12 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final long firstSliceDestination = newDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); if (!allowCreation) { - removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); - modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, + modifiedBuilders.resetWritableChunkToBackingStore(modifiedBuildersResettableChunk, firstSliceDestination); shiftDataBuilders.resetWritableChunkToBackingStore(shiftDataBuildersResettableChunk, firstSliceDestination); @@ -782,16 +775,16 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final int backingChunkOffset = Math.toIntExact(newDestination - firstBackingChunkDestination); if (allowCreation) { final WritableRowSet newRowSet = - extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset); + extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset); final QueryTable newTable = makeSubTable(newRowSet); linkTableReferences(newTable); tablesBackingChunk.set(backingChunkOffset, newTable); } else { // We will never try to create this table again, or accumulate further state for it. tablesBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE); - addedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); - removedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); - modifiedRowSetsBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM); + addedBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); + removedBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); + modifiedBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_ROW_SET_BUILDER); shiftDataBuildersBackingChunk.set(backingChunkOffset, NONEXISTENT_TABLE_SHIFT_BUILDER); } }); @@ -823,7 +816,7 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedRowSetsResettableChunk = + final ResettableWritableObjectChunk removedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final RowSequence.Iterator removedDestinationsIterator = removedDestinations.getRowSequenceIterator()) { // Destinations that were completely removed can't have any additions, modifications, or shifts. @@ -831,14 +824,14 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = - removedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk removedBuildersBackingChunk = + removedBuildersResettableChunk.asWritableObjectChunk(); while (removedDestinationsIterator.hasMore()) { final long firstSliceDestination = removedDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; final RowSequence removedDestinationsSlice = @@ -859,7 +852,7 @@ private void propagateUpdatesToRemovedDestinations(@NotNull final RowSequence re downstream.added = RowSetFactory.empty(); downstream.removed = - nullToEmpty(extractAndClearBuilderRandom(removedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset)); downstream.modified = RowSetFactory.empty(); downstream.shifted = RowSetShiftData.EMPTY; downstream.modifiedColumnSet = ModifiedColumnSet.EMPTY; @@ -879,14 +872,11 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m } try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedRowSetsResettableChunk = + final ResettableWritableObjectChunk addedBuildersResettableChunk = initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; - final ResettableWritableObjectChunk addedRowSetsSequentialResettableChunk = - !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; - - final ResettableWritableObjectChunk removedRowSetsResettableChunk = + final ResettableWritableObjectChunk removedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedRowSetsResettableChunk = + final ResettableWritableObjectChunk modifiedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); @@ -896,15 +886,15 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m // noinspection unchecked final ObjectChunk tablesBackingChunk = tablesResettableChunk.asObjectChunk(); // noinspection unchecked - final WritableObjectChunk addedRowSetsBackingChunk = - addedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk removedRowSetsBackingChunk = - removedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk removedBuildersBackingChunk = + removedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked - final WritableObjectChunk modifiedRowSetsBackingChunk = - modifiedRowSetsResettableChunk.asWritableObjectChunk(); + final WritableObjectChunk modifiedBuildersBackingChunk = + modifiedBuildersResettableChunk.asWritableObjectChunk(); // noinspection unchecked final WritableObjectChunk shiftDataBuildersBackingChunk = shiftDataBuildersResettableChunk.asWritableObjectChunk(); @@ -914,12 +904,12 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); // The (valid) assumption is that the other write-through resets will address the same range. - addedRowSetBuilders.resetWritableChunkToBackingStore(addedRowSetsResettableChunk, + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); - removedRowSetBuilders.resetWritableChunkToBackingStore(removedRowSetsResettableChunk, + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); - modifiedRowSetBuilders.resetWritableChunkToBackingStore(modifiedRowSetsResettableChunk, + modifiedBuilders.resetWritableChunkToBackingStore(modifiedBuildersResettableChunk, firstSliceDestination); shiftDataBuilders.resetWritableChunkToBackingStore(shiftDataBuildersResettableChunk, firstSliceDestination); @@ -941,12 +931,12 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m final TableUpdateImpl downstream = new TableUpdateImpl(); downstream.added = - nullToEmpty(extractAndClearBuilderRandom(addedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); downstream.removed = - nullToEmpty(extractAndClearBuilderRandom(removedRowSetsBackingChunk, backingChunkOffset)); + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset)); downstream.modified = stepValuesModified - ? nullToEmpty(extractAndClearBuilderRandom(modifiedRowSetsBackingChunk, backingChunkOffset)) + ? nullToEmpty(extractAndClearBuilderRandom(modifiedBuildersBackingChunk, backingChunkOffset)) : RowSetFactory.empty(); downstream.shifted = extractAndClearShiftDataBuilder(shiftDataBuildersBackingChunk, backingChunkOffset); @@ -975,7 +965,7 @@ private static WritableRowSet extractAndClearBuilderRandom( @NotNull final WritableObjectChunk rowSetChunk, final int offset) { final RowSetBuilderRandom builder = rowSetChunk.get(offset); - Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM, + Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER, "NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM"); if (builder != null) { final WritableRowSet rowSet = builder.build(); @@ -989,8 +979,6 @@ private static WritableRowSet extractAndClearBuilderSequential( @NotNull final WritableObjectChunk rowSetChunk, final int offset) { final RowSetBuilderSequential builder = rowSetChunk.get(offset); - Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL, - "NONEXISTENT_TABLE_ROW_SET_BUILDER_SEQUENTIAL"); if (builder != null) { final WritableRowSet rowSet = builder.build(); rowSetChunk.set(offset, null); From 69dc9dae02787afa8e5f684b507349bdefc6d363 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Fri, 16 Sep 2022 09:37:53 -0700 Subject: [PATCH 09/25] can we get auto-spotless? --- .../engine/table/impl/by/PartitionByChunkedOperator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 18aec8601f5..8d50f8cf3d2 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -936,7 +936,8 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m downstream.removed = nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset)); downstream.modified = stepValuesModified - ? nullToEmpty(extractAndClearBuilderRandom(modifiedBuildersBackingChunk, backingChunkOffset)) + ? nullToEmpty( + extractAndClearBuilderRandom(modifiedBuildersBackingChunk, backingChunkOffset)) : RowSetFactory.empty(); downstream.shifted = extractAndClearShiftDataBuilder(shiftDataBuildersBackingChunk, backingChunkOffset); From a29e6553d27a1e53497a19d230183245a8c7e21c Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 19 Sep 2022 10:16:53 -0700 Subject: [PATCH 10/25] add'l PR comments addressed --- .../impl/by/PartitionByChunkedOperator.java | 130 ++++++++++-------- 1 file changed, 73 insertions(+), 57 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 8d50f8cf3d2..44724117a9c 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -91,16 +91,15 @@ public interface AttributeCopier { private final String callSite; private final ObjectArraySource tables; - private final ObjectArraySource addedBuildersSequential; - private final ObjectArraySource addedBuilders; - private final ObjectArraySource removedBuilders; - private final ObjectArraySource modifiedBuilders; + private final ObjectArraySource addedBuilders; + private final ObjectArraySource removedBuilders; + private final ObjectArraySource modifiedBuilders; private final ObjectArraySource shiftDataBuilders; private final ModifiedColumnSet resultModifiedColumnSet; private final ModifiedColumnSet.Transformer upstreamToResultTransformer; - private volatile boolean initialized; + private boolean initialized; private volatile Table resultTable; private volatile LivenessReferent aggregationUpdateListener; @@ -144,13 +143,12 @@ public interface AttributeCopier { @NotNull final String... keyColumnNames) { this.parentTable = parentTable; this.resultName = resultName; - this.initialized = false; + initialized = false; callSite = QueryPerformanceRecorder.getCallerLine(); tables = new ObjectArraySource<>(QueryTable.class); - addedBuildersSequential = new ObjectArraySource<>(RowSetBuilderSequential.class); - addedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + addedBuilders = new ObjectArraySource<>(Object.class); // Note: Sub-tables always share their ColumnSource map with the parent table, so they can all use this result // MCS. @@ -165,8 +163,8 @@ public interface AttributeCopier { } if (parentTable.isRefreshing()) { - removedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); - modifiedBuilders = new ObjectArraySource<>(RowSetBuilderRandom.class); + removedBuilders = new ObjectArraySource<>(Object.class); + modifiedBuilders = new ObjectArraySource<>(Object.class); shiftDataBuilders = new ObjectArraySource<>(RowSetShiftData.SmartCoalescingBuilder.class); final Set keyColumnNameSet = Arrays.stream(keyColumnNames).collect(Collectors.toSet()); @@ -208,7 +206,7 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; if (!initialized) { - accumulateToBuilderSequential(addedBuildersSequential, inputRowKeysAsOrdered, 0, chunkSize, - destination); + accumulateToBuilderSequential(addedBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); } else { accumulateToBuilderRandom(addedBuilders, inputRowKeysAsOrdered, 0, chunkSize, destination); } @@ -337,7 +334,7 @@ public boolean addChunk(final SingletonContext singletonContext, final int chunk @Override public boolean addRowSet(SingletonContext context, RowSet rowSet, long destination) { if (!initialized) { - accumulateToBuilderSequential(addedBuildersSequential, rowSet, destination); + accumulateToBuilderSequential(addedBuilders, rowSet, destination); } else { accumulateToBuilderRandom(addedBuilders, rowSet, destination); } @@ -398,27 +395,25 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long } private static void accumulateToBuilderSequential( - @NotNull final ObjectArraySource rowSetColumn, + @NotNull final ObjectArraySource rowSetColumn, @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { - final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); - // slice the chunk to the start and length - LongChunk sliced = rowKeysToAdd.slice(start, length); + final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with these keys final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); - newBuilder.appendOrderedRowKeysChunk(sliced); + newBuilder.appendOrderedRowKeysChunk(rowKeysToAdd, start, length); rowSetColumn.set(destination, newBuilder); return; } // add the keys to the stored builder - builder.appendOrderedRowKeysChunk(sliced); + builder.appendOrderedRowKeysChunk(rowKeysToAdd, start, length); } private static void accumulateToBuilderSequential( - @NotNull final ObjectArraySource rowSetColumn, + @NotNull final ObjectArraySource rowSetColumn, @NotNull final RowSet rowSetToAdd, final long destination) { - final RowSetBuilderSequential builder = rowSetColumn.getUnsafe(destination); + final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with this rowset final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); @@ -431,29 +426,27 @@ private static void accumulateToBuilderSequential( } - private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { - final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); + final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } - // slice the chunk to the start and length - LongChunk sliced = rowKeysToAdd.slice(start, length); if (builder == null) { // create (and store) a new builder, fill with these keys final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); - newBuilder.addRowKeysChunk(sliced); + newBuilder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); rowSetColumn.set(destination, newBuilder); return; } // add the keys to the stored builder - builder.addRowKeysChunk(sliced); + builder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); } - private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, @NotNull final RowSet rowSetToAdd, final long destination) { - final RowSetBuilderRandom builder = rowSetColumn.getUnsafe(destination); + final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); if (builder == NONEXISTENT_TABLE_ROW_SET_BUILDER) { return; } @@ -477,19 +470,46 @@ private boolean appendShifts(@NotNull final LongChunk preShif } if (builder == null) { final RowSet tableRowSet = tables.getUnsafe(destination).getRowSet(); - final RowSetBuilderRandom removedRowSetBuilder = removedBuilders.getUnsafe(destination); + final RowSetBuilderRandom removedRowSetBuilder = + (RowSetBuilderRandom) removedBuilders.getUnsafe(destination); final RowSet preShiftKeys; if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); } else { - // we want to keep the builder in `removedRowSetBuilders` ready for a call to `extractAndClearRowSet` so - // we remake the builder after this call - try (final RowSet rs = removedRowSetBuilder.build()) { - preShiftKeys = tableRowSet.minus(rs); - RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); - newBuilder.addRowSet(rs); - removedBuilders.set(destination, newBuilder); + // dummy builder to prevent allow a subsequent call to build()` + class PrecomputedRowSetBuilder implements RowSetBuilderRandom { + WritableRowSet rowSet; + + public PrecomputedRowSetBuilder(final WritableRowSet rowSet) { + this.rowSet = rowSet; + } + + @Override + public WritableRowSet build() { + // make sure to release our reference to the rowset after `build()` is called + WritableRowSet tmp = rowSet; + rowSet = null; + return tmp; + } + + @Override + public void addKey(long rowKey) { + throw (new UnsupportedOperationException("PrecomputedRowSetBuilder cannot be modified)")); + } + + @Override + public void addRange(long firstRowKey, long lastRowKey) { + throw (new UnsupportedOperationException("PrecomputedRowSetBuilder cannot be modified")); + } } + + final WritableRowSet rs = removedRowSetBuilder.build(); + preShiftKeys = tableRowSet.minus(rs); + + // we want to keep the builder in `removedRowSetBuilders` ready for a call to `build()` so replace it + // with our new builder type + RowSetBuilderRandom newBuilder = new PrecomputedRowSetBuilder(rs); + removedBuilders.set(destination, newBuilder); } shiftDataBuilders.set(destination, builder = new RowSetShiftData.SmartCoalescingBuilder(preShiftKeys)); } @@ -520,9 +540,6 @@ private boolean appendShifts(@NotNull final LongChunk preShif public void ensureCapacity(final long tableSize) { tables.ensureCapacity(tableSize); addedBuilders.ensureCapacity(tableSize); - if (!initialized) { - addedBuildersSequential.ensureCapacity(tableSize); - } if (parentTable.isRefreshing()) { removedBuilders.ensureCapacity(tableSize); modifiedBuilders.ensureCapacity(tableSize); @@ -540,6 +557,7 @@ public void startTrackingPrevValues() {} @Override public void propagateInitialState(@NotNull final QueryTable resultTable) { + Assert.neqTrue(initialized, "initialized"); final RowSet initialDestinations = resultTable.getRowSet(); if (initialDestinations.isNonempty()) { // This is before resultTable and aggregationUpdateListener are set (if they will be). We're still in our @@ -548,7 +566,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk addedBuildersResettableChunk = - !initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + ResettableWritableObjectChunk.makeResettableChunk(); final RowSequence.Iterator initialDestinationsIterator = initialDestinations.getRowSequenceIterator()) { @@ -563,8 +581,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final long firstSliceDestination = initialDestinationsIterator.peekNextKey(); final long firstBackingChunkDestination = tables.resetWritableChunkToBackingStore(tablesResettableChunk, firstSliceDestination); - // use the sequential builders during initialization - addedBuildersSequential.resetWritableChunkToBackingStore(addedBuildersResettableChunk, + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + tablesBackingChunk.size() - 1; @@ -574,6 +591,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { initialDestinationsSlice.forAllRowKeys((final long destinationToInitialize) -> { final int backingChunkOffset = Math.toIntExact(destinationToInitialize - firstBackingChunkDestination); + // we use sequential builders during initialization final WritableRowSet initialRowSet = extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset); final QueryTable newTable = makeSubTable(initialRowSet); @@ -727,11 +745,11 @@ private void propagateNewDestinations(@NotNull final RowSequence newDestinations final boolean setCallSite = QueryPerformanceRecorder.setCallsite(callSite); try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = + final ResettableWritableObjectChunk addedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedBuildersResettableChunk = + final ResettableWritableObjectChunk removedBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk modifiedBuildersResettableChunk = + final ResettableWritableObjectChunk modifiedBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk shiftDataBuildersResettableChunk = allowCreation ? null : ResettableWritableObjectChunk.makeResettableChunk(); @@ -873,7 +891,7 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m try (final ResettableWritableObjectChunk tablesResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk addedBuildersResettableChunk = - initialized ? ResettableWritableObjectChunk.makeResettableChunk() : null; + ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk removedBuildersResettableChunk = ResettableWritableObjectChunk.makeResettableChunk(); final ResettableWritableObjectChunk modifiedBuildersResettableChunk = @@ -906,7 +924,6 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m // The (valid) assumption is that the other write-through resets will address the same range. addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); - removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); modifiedBuilders.resetWritableChunkToBackingStore(modifiedBuildersResettableChunk, @@ -932,7 +949,6 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m downstream.added = nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); - downstream.removed = nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset)); downstream.modified = stepValuesModified @@ -963,26 +979,26 @@ private void propagateUpdatesToModifiedDestinations(@NotNull final RowSequence m } private static WritableRowSet extractAndClearBuilderRandom( - @NotNull final WritableObjectChunk rowSetChunk, + @NotNull final WritableObjectChunk builderChunk, final int offset) { - final RowSetBuilderRandom builder = rowSetChunk.get(offset); + final RowSetBuilderRandom builder = builderChunk.get(offset); Assert.neq(builder, "builder", NONEXISTENT_TABLE_ROW_SET_BUILDER, - "NONEXISTENT_TABLE_ROW_SET_BUILDER_RANDOM"); + "NONEXISTENT_TABLE_ROW_SET_BUILDER"); if (builder != null) { final WritableRowSet rowSet = builder.build(); - rowSetChunk.set(offset, null); + builderChunk.set(offset, null); return rowSet; } return null; } private static WritableRowSet extractAndClearBuilderSequential( - @NotNull final WritableObjectChunk rowSetChunk, + @NotNull final WritableObjectChunk builderChunk, final int offset) { - final RowSetBuilderSequential builder = rowSetChunk.get(offset); + final RowSetBuilderSequential builder = builderChunk.get(offset); if (builder != null) { final WritableRowSet rowSet = builder.build(); - rowSetChunk.set(offset, null); + builderChunk.set(offset, null); return rowSet; } return null; From 51f4c813f76bd1c6644a8199c3acb438190222cc Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 19 Sep 2022 10:20:20 -0700 Subject: [PATCH 11/25] fixed a silly comment --- .../engine/table/impl/by/PartitionByChunkedOperator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 44724117a9c..891fd7d501e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -476,7 +476,7 @@ private boolean appendShifts(@NotNull final LongChunk preShif if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); } else { - // dummy builder to prevent allow a subsequent call to build()` + // dummy builder to allow a subsequent call to build()` class PrecomputedRowSetBuilder implements RowSetBuilderRandom { WritableRowSet rowSet; From abd7e2192afe1760a5d58e2e3410cb9e8a68ecf8 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 19 Sep 2022 11:27:47 -0700 Subject: [PATCH 12/25] extracted the local class to allow general usage --- .../impl/PrecomputedRowSetBuilderRandom.java | 50 +++++++++++++++++++ .../impl/by/PartitionByChunkedOperator.java | 33 ++---------- 2 files changed, 53 insertions(+), 30 deletions(-) create mode 100644 engine/table/src/main/java/io/deephaven/engine/table/impl/PrecomputedRowSetBuilderRandom.java diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/PrecomputedRowSetBuilderRandom.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/PrecomputedRowSetBuilderRandom.java new file mode 100644 index 00000000000..cecaaefa74d --- /dev/null +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/PrecomputedRowSetBuilderRandom.java @@ -0,0 +1,50 @@ +package io.deephaven.engine.table.impl; + +import io.deephaven.engine.rowset.RowSetBuilderRandom; +import io.deephaven.engine.rowset.WritableRowSet; +import io.deephaven.engine.table.impl.by.PartitionByChunkedOperator; +import org.jetbrains.annotations.NotNull; + +/** + * This is a niche class that allows an existing {@link WritableRowSet rowset} to masquerade as a + * {@link RowSetBuilderRandom} for the sake of efficient processing. + * + * General usage would embed this in a collection with actual {@link RowSetBuilderRandom} and process all items + * similarly. See + * {@link PartitionByChunkedOperator#appendShifts(io.deephaven.chunk.LongChunk, io.deephaven.chunk.LongChunk, int, int, long)} + * and {@link PartitionByChunkedOperator#extractAndClearBuilderRandom(io.deephaven.chunk.WritableObjectChunk, int)} for + * an example. + */ + +public class PrecomputedRowSetBuilderRandom implements RowSetBuilderRandom { + WritableRowSet rowSet; + + private PrecomputedRowSetBuilderRandom(@NotNull final WritableRowSet rowSet) { + this.rowSet = rowSet; + } + + @Override + public WritableRowSet build() { + if (rowSet == null) { + throw new IllegalStateException("PrecomputedRowSetBuilderRandom - build() already called)"); + } + // make sure to release our reference to the rowset after `build()` is called + WritableRowSet tmp = rowSet; + rowSet = null; + return tmp; + } + + @Override + public void addKey(long rowKey) { + throw new UnsupportedOperationException("PrecomputedRowSetBuilderRandom does not allow modifications)"); + } + + @Override + public void addRange(long firstRowKey, long lastRowKey) { + throw new UnsupportedOperationException("PrecomputedRowSetBuilderRandom does not allow modifications"); + } + + public static PrecomputedRowSetBuilderRandom createFromRowSet(@NotNull final WritableRowSet rowSet) { + return new PrecomputedRowSetBuilderRandom(rowSet); + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index 891fd7d501e..e12f155c060 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -29,6 +29,7 @@ import io.deephaven.engine.table.TableListener; import io.deephaven.engine.table.TableUpdate; import io.deephaven.engine.table.impl.ConstituentDependency; +import io.deephaven.engine.table.impl.PrecomputedRowSetBuilderRandom; import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.TableUpdateImpl; import io.deephaven.engine.table.impl.perf.QueryPerformanceRecorder; @@ -476,39 +477,11 @@ private boolean appendShifts(@NotNull final LongChunk preShif if (removedRowSetBuilder == null) { preShiftKeys = tableRowSet.copy(); } else { - // dummy builder to allow a subsequent call to build()` - class PrecomputedRowSetBuilder implements RowSetBuilderRandom { - WritableRowSet rowSet; - - public PrecomputedRowSetBuilder(final WritableRowSet rowSet) { - this.rowSet = rowSet; - } - - @Override - public WritableRowSet build() { - // make sure to release our reference to the rowset after `build()` is called - WritableRowSet tmp = rowSet; - rowSet = null; - return tmp; - } - - @Override - public void addKey(long rowKey) { - throw (new UnsupportedOperationException("PrecomputedRowSetBuilder cannot be modified)")); - } - - @Override - public void addRange(long firstRowKey, long lastRowKey) { - throw (new UnsupportedOperationException("PrecomputedRowSetBuilder cannot be modified")); - } - } - final WritableRowSet rs = removedRowSetBuilder.build(); preShiftKeys = tableRowSet.minus(rs); - // we want to keep the builder in `removedRowSetBuilders` ready for a call to `build()` so replace it - // with our new builder type - RowSetBuilderRandom newBuilder = new PrecomputedRowSetBuilder(rs); + // no future modifications are expected, replace the exhausted builder with a dummy for compatibility + RowSetBuilderRandom newBuilder = PrecomputedRowSetBuilderRandom.createFromRowSet(rs); removedBuilders.set(destination, newBuilder); } shiftDataBuilders.set(destination, builder = new RowSetShiftData.SmartCoalescingBuilder(preShiftKeys)); From ba3567f945f2bbaff3fd31817b1f6554ddf8a740 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Tue, 20 Sep 2022 10:15:14 -0700 Subject: [PATCH 13/25] Using sequential builders to accelerate initial GroupBy creation --- .../table/impl/by/GroupByChunkedOperator.java | 79 +++++++++++++++---- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index fb8018e0ddf..ca70441163f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -4,21 +4,19 @@ package io.deephaven.engine.table.impl.by; import io.deephaven.base.verify.Assert; +import io.deephaven.chunk.*; import io.deephaven.chunk.attributes.ChunkLengths; import io.deephaven.chunk.attributes.ChunkPositions; import io.deephaven.chunk.attributes.Values; import io.deephaven.datastructures.util.CollectionUtil; -import io.deephaven.engine.rowset.RowSetFactory; -import io.deephaven.engine.table.*; -import io.deephaven.engine.rowset.*; import io.deephaven.engine.liveness.LivenessReferent; -import io.deephaven.engine.table.ModifiedColumnSet; +import io.deephaven.engine.rowset.*; +import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.table.*; import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.sources.ObjectArraySource; import io.deephaven.engine.table.impl.sources.aggregate.AggregateColumnSource; -import io.deephaven.chunk.*; -import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; -import io.deephaven.engine.rowset.chunkattributes.RowKeys; import org.jetbrains.annotations.NotNull; import java.util.Arrays; @@ -41,6 +39,7 @@ public final class GroupByChunkedOperator private final boolean registeredWithHelper; private final boolean live; private final ObjectArraySource rowSets; + private ObjectArraySource addedBuilders; private final String[] inputColumnNames; private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; @@ -48,6 +47,7 @@ public final class GroupByChunkedOperator private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; private boolean someKeyHasModifies; + private boolean initialized; GroupByChunkedOperator(@NotNull final QueryTable inputTable, final boolean registeredWithHelper, @NotNull final MatchPair... resultColumnPairs) { @@ -55,6 +55,7 @@ public final class GroupByChunkedOperator this.registeredWithHelper = registeredWithHelper; live = inputTable.isRefreshing(); rowSets = new ObjectArraySource<>(WritableRowSet.class); + addedBuilders = new ObjectArraySource<>(RowSetBuilderSequential.class); resultColumns = Arrays.stream(resultColumnPairs).collect(Collectors.toMap(MatchPair::leftColumn, matchPair -> AggregateColumnSource .make(inputTable.getColumnSource(matchPair.rightColumn()), rowSets), @@ -65,6 +66,7 @@ public final class GroupByChunkedOperator } else { resultInputsModifiedColumnSet = null; } + initialized = false; } @Override @@ -214,20 +216,30 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long private void addChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { - final WritableRowSet rowSet = rowSetForSlot(destination); - final boolean wasEmpty = rowSet.isEmpty(); - rowSet.insert(indices, start, length); - if (wasEmpty && rowSet.isNonempty()) { - onReincarnated(destination); + if (!initialized) { + final RowSetBuilderSequential builder = builderForSlot(destination); + builder.appendOrderedRowKeysChunk(indices, start, length); + } else { + final WritableRowSet rowSet = rowSetForSlot(destination); + final boolean wasEmpty = rowSet.isEmpty(); + rowSet.insert(indices, start, length); + if (wasEmpty && rowSet.isNonempty()) { + onReincarnated(destination); + } } } private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destination) { - final WritableRowSet rowSet = rowSetForSlot(destination); - final boolean wasEmpty = rowSet.isEmpty(); - rowSet.insert(addRowSet); - if (wasEmpty && rowSet.isNonempty()) { - onReincarnated(destination); + if (!initialized) { + final RowSetBuilderSequential builder = builderForSlot(destination); + builder.appendRowSequence(addRowSet); + } else { + final WritableRowSet rowSet = rowSetForSlot(destination); + final boolean wasEmpty = rowSet.isEmpty(); + rowSet.insert(addRowSet); + if (wasEmpty && rowSet.isNonempty()) { + onReincarnated(destination); + } } } @@ -258,9 +270,22 @@ private WritableRowSet rowSetForSlot(final long destination) { return rowSet; } + private RowSetBuilderSequential builderForSlot(final long destination) { + RowSetBuilderSequential builder = addedBuilders.getUnsafe(destination); + if (builder == null) { + final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); + addedBuilders.set(destination, builder = newBuilder); + } + return builder; + } + + @Override public void ensureCapacity(final long tableSize) { rowSets.ensureCapacity(tableSize); + if (!initialized) { + addedBuilders.ensureCapacity(tableSize); + } } @Override @@ -278,6 +303,26 @@ public void startTrackingPrevValues() { resultColumns.values().forEach(ColumnSource::startTrackingPrevValues); } + @Override + public void propagateInitialState(@NotNull final QueryTable resultTable) { + Assert.neqTrue(initialized, "initialized"); + final RowSet initialDestinations = resultTable.getRowSet(); + if (initialDestinations.isNonempty()) { + // turn all the builders into rowsets + initialDestinations.forAllRowKeys(destination -> { + // build the rowset and store it + final WritableRowSet rowSet = addedBuilders.getUnsafe(destination).build(); + rowSets.set(destination, rowSet); + + // clear the builder slots + addedBuilders.set(destination, null); + }); + // free the storage from the builders + addedBuilders = null; + } + initialized = true; + } + @Override public UnaryOperator initializeRefreshing(@NotNull final QueryTable resultTable, @NotNull final LivenessReferent aggregationUpdateListener) { From 7f2496fd769969c9a0a98edb23c73af41fa5cb93 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Tue, 20 Sep 2022 12:41:15 -0700 Subject: [PATCH 14/25] bugfix: enable tracking on rowset after build() --- .../deephaven/engine/table/impl/by/GroupByChunkedOperator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index ca70441163f..541a4ffc470 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -312,7 +312,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { initialDestinations.forAllRowKeys(destination -> { // build the rowset and store it final WritableRowSet rowSet = addedBuilders.getUnsafe(destination).build(); - rowSets.set(destination, rowSet); + rowSets.set(destination, live ? rowSet.toTracking() : rowSet); // clear the builder slots addedBuilders.set(destination, null); From d4f163a86451b3fb1af5293d697342aa5b3a821f Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 21 Sep 2022 11:05:56 -0700 Subject: [PATCH 15/25] changes to allow more efficient updates (WIP) --- .../table/impl/by/GroupByChunkedOperator.java | 309 ++++++++++++++---- 1 file changed, 240 insertions(+), 69 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 541a4ffc470..93ff5d47c4e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -14,10 +14,12 @@ import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; import io.deephaven.engine.rowset.chunkattributes.RowKeys; import io.deephaven.engine.table.*; +import io.deephaven.engine.table.impl.PrecomputedRowSetBuilderRandom; import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.sources.ObjectArraySource; import io.deephaven.engine.table.impl.sources.aggregate.AggregateColumnSource; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.LinkedHashMap; @@ -39,7 +41,12 @@ public final class GroupByChunkedOperator private final boolean registeredWithHelper; private final boolean live; private final ObjectArraySource rowSets; - private ObjectArraySource addedBuilders; + private final ObjectArraySource addedBuilders; + private final ObjectArraySource removedBuilders; + private RowSetBuilderRandom stepUpdatedDestinations; + + private final ObjectArraySource modifiedBuilders; + private final String[] inputColumnNames; private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; @@ -55,7 +62,7 @@ public final class GroupByChunkedOperator this.registeredWithHelper = registeredWithHelper; live = inputTable.isRefreshing(); rowSets = new ObjectArraySource<>(WritableRowSet.class); - addedBuilders = new ObjectArraySource<>(RowSetBuilderSequential.class); + addedBuilders = new ObjectArraySource<>(Object.class); resultColumns = Arrays.stream(resultColumnPairs).collect(Collectors.toMap(MatchPair::leftColumn, matchPair -> AggregateColumnSource .make(inputTable.getColumnSource(matchPair.rightColumn()), rowSets), @@ -63,8 +70,12 @@ public final class GroupByChunkedOperator inputColumnNames = MatchPair.getRightColumns(resultColumnPairs); if (live) { resultInputsModifiedColumnSet = inputTable.newModifiedColumnSet(inputColumnNames); + removedBuilders = new ObjectArraySource<>(Object.class); + modifiedBuilders = new ObjectArraySource<>(Object.class); } else { resultInputsModifiedColumnSet = null; + removedBuilders = null; + modifiedBuilders = null; } initialized = false; } @@ -77,13 +88,12 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk 0; // noinspection unchecked - final LongChunk inputIndicesAsOrdered = (LongChunk) inputRowKeys; + final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; for (int ii = 0; ii < startPositions.size(); ++ii) { final int startPosition = startPositions.get(ii); final int runLength = length.get(ii); final long destination = destinations.get(startPosition); - - addChunk(inputIndicesAsOrdered, startPosition, runLength, destination); + addChunk(inputRowKeysAsOrdered, startPosition, runLength, destination); } stateModified.fillWithValue(0, startPositions.size(), true); } @@ -96,13 +106,13 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk 0; // noinspection unchecked - final LongChunk inputIndicesAsOrdered = (LongChunk) inputRowKeys; + final LongChunk inputRowKeysAsOrdered = (LongChunk) inputRowKeys; for (int ii = 0; ii < startPositions.size(); ++ii) { final int startPosition = startPositions.get(ii); final int runLength = length.get(ii); final long destination = destinations.get(startPosition); - - removeChunk(inputIndicesAsOrdered, startPosition, runLength, destination); + accumulateToBuilderRandom(removedBuilders, inputRowKeysAsOrdered, startPosition, runLength, destination); + stepUpdatedDestinations.addKey(destination); } stateModified.fillWithValue(0, startPositions.size(), true); } @@ -217,74 +227,147 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long private void addChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { if (!initialized) { - final RowSetBuilderSequential builder = builderForSlot(destination); - builder.appendOrderedRowKeysChunk(indices, start, length); + // during initialization, all rows are guaranteed to be in-order + accumulateToBuilderSequential(addedBuilders, indices, start, length, destination); } else { - final WritableRowSet rowSet = rowSetForSlot(destination); - final boolean wasEmpty = rowSet.isEmpty(); - rowSet.insert(indices, start, length); - if (wasEmpty && rowSet.isNonempty()) { - onReincarnated(destination); - } + accumulateToBuilderRandom(addedBuilders, indices, start, length, destination); + } + if (stepUpdatedDestinations != null) { + stepUpdatedDestinations.addKey(destination); } } private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destination) { if (!initialized) { - final RowSetBuilderSequential builder = builderForSlot(destination); - builder.appendRowSequence(addRowSet); + // during initialization, all rows are guaranteed to be in-order + accumulateToBuilderSequential(addedBuilders, addRowSet, destination); } else { - final WritableRowSet rowSet = rowSetForSlot(destination); - final boolean wasEmpty = rowSet.isEmpty(); - rowSet.insert(addRowSet); - if (wasEmpty && rowSet.isNonempty()) { - onReincarnated(destination); - } + accumulateToBuilderRandom(addedBuilders, addRowSet, destination); + } + if (stepUpdatedDestinations != null) { + stepUpdatedDestinations.addKey(destination); } } private void removeChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { - final WritableRowSet rowSet = rowSetForSlot(destination); - final boolean wasNonEmpty = rowSet.isNonempty(); - rowSet.remove(indices, start, length); - if (wasNonEmpty && rowSet.isEmpty()) { - onEmptied(destination); - } + accumulateToBuilderRandom(removedBuilders, indices, start, length, destination); + stepUpdatedDestinations.addKey(destination); } - private void doShift(@NotNull final LongChunk preShiftIndices, - @NotNull final LongChunk postShiftIndices, + private void doShift(@NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, final int startPosition, final int runLength, final long destination) { - final WritableRowSet rowSet = rowSetForSlot(destination); - rowSet.remove(preShiftIndices, startPosition, runLength); - rowSet.insert(postShiftIndices, startPosition, runLength); + // treat shift as remove + add + removeChunk(preShiftRowKeys, startPosition, runLength, destination); + addChunk(postShiftRowKeys, startPosition, runLength, destination); } - private WritableRowSet rowSetForSlot(final long destination) { - WritableRowSet rowSet = rowSets.getUnsafe(destination); - if (rowSet == null) { - final WritableRowSet empty = RowSetFactory.empty(); - rowSets.set(destination, rowSet = live ? empty.toTracking() : empty); + private static void accumulateToBuilderSequential( + @NotNull final ObjectArraySource rowSetColumn, + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { + final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); + if (builder == null) { + // create (and store) a new builder, fill with these keys + final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); + newBuilder.appendOrderedRowKeysChunk(rowKeysToAdd, start, length); + rowSetColumn.set(destination, newBuilder); + return; } - return rowSet; + // add the keys to the stored builder + builder.appendOrderedRowKeysChunk(rowKeysToAdd, start, length); } - private RowSetBuilderSequential builderForSlot(final long destination) { - RowSetBuilderSequential builder = addedBuilders.getUnsafe(destination); + private static void accumulateToBuilderSequential( + @NotNull final ObjectArraySource rowSetColumn, + @NotNull final RowSet rowSetToAdd, final long destination) { + final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); if (builder == null) { + // create (and store) a new builder, fill with this rowset final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); - addedBuilders.set(destination, builder = newBuilder); + newBuilder.appendRowSequence(rowSetToAdd); + rowSetColumn.set(destination, newBuilder); + return; + } + // add the rowset to the stored builder + builder.appendRowSequence(rowSetToAdd); + } + + + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { + final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); + if (builder == null) { + // create (and store) a new builder, fill with these keys + final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); + newBuilder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); + rowSetColumn.set(destination, newBuilder); + return; + } + // add the keys to the stored builder + builder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); + } + + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + @NotNull final RowSet rowSetToAdd, final long destination) { + final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); + if (builder == null) { + // create (and store) a new builder, fill with this rowset + final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); + newBuilder.addRowSet(rowSetToAdd); + rowSetColumn.set(destination, newBuilder); + return; + } + // add the rowset to the stored builder + builder.addRowSet(rowSetToAdd); + } + + private static WritableRowSet extractAndClearBuilderRandom( + @NotNull final WritableObjectChunk builderChunk, + final int offset) { + final RowSetBuilderRandom builder = builderChunk.get(offset); + if (builder != null) { + final WritableRowSet rowSet = builder.build(); + builderChunk.set(offset, null); + return rowSet; + } + return null; + } + + private static WritableRowSet extractAndClearBuilderSequential( + @NotNull final WritableObjectChunk builderChunk, + final int offset) { + final RowSetBuilderSequential builder = builderChunk.get(offset); + if (builder != null) { + final WritableRowSet rowSet = builder.build(); + builderChunk.set(offset, null); + return rowSet; } - return builder; + return null; } + private static WritableRowSet nullToEmpty(@Nullable final WritableRowSet rowSet) { + return rowSet == null ? RowSetFactory.empty() : rowSet; + } + + private WritableRowSet rowSetForSlot(final long destination) { + WritableRowSet rowSet = rowSets.getUnsafe(destination); + if (rowSet == null) { + final WritableRowSet empty = RowSetFactory.empty(); + rowSets.set(destination, rowSet = live ? empty.toTracking() : empty); + } + return rowSet; + } @Override public void ensureCapacity(final long tableSize) { rowSets.ensureCapacity(tableSize); - if (!initialized) { - addedBuilders.ensureCapacity(tableSize); + addedBuilders.ensureCapacity(tableSize); + if (live) { + removedBuilders.ensureCapacity(tableSize); + modifiedBuilders.ensureCapacity(tableSize); } } @@ -303,26 +386,6 @@ public void startTrackingPrevValues() { resultColumns.values().forEach(ColumnSource::startTrackingPrevValues); } - @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { - Assert.neqTrue(initialized, "initialized"); - final RowSet initialDestinations = resultTable.getRowSet(); - if (initialDestinations.isNonempty()) { - // turn all the builders into rowsets - initialDestinations.forAllRowKeys(destination -> { - // build the rowset and store it - final WritableRowSet rowSet = addedBuilders.getUnsafe(destination).build(); - rowSets.set(destination, live ? rowSet.toTracking() : rowSet); - - // clear the builder slots - addedBuilders.set(destination, null); - }); - // free the storage from the builders - addedBuilders = null; - } - initialized = true; - } - @Override public UnaryOperator initializeRefreshing(@NotNull final QueryTable resultTable, @NotNull final LivenessReferent aggregationUpdateListener) { @@ -376,6 +439,7 @@ public ModifiedColumnSet apply(@NotNull final ModifiedColumnSet upstreamModified @Override public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + stepUpdatedDestinations = RowSetFactory.builderRandom(); stepValuesModified = upstream.modified().isNonempty() && upstream.modifiedColumnSet().nonempty() && upstream.modifiedColumnSet().containsAny(resultInputsModifiedColumnSet); someKeyHasAddsOrRemoves = false; @@ -383,8 +447,115 @@ public void resetForStep(@NotNull final TableUpdate upstream, final int starting } @Override - public void propagateUpdates(@NotNull final TableUpdate downstream, - @NotNull final RowSet newDestinations) { + public void propagateInitialState(@NotNull final QueryTable resultTable) { + Assert.neqTrue(initialized, "initialized"); + final RowSet initialDestinations = resultTable.getRowSet(); + + // use the builders to create the initial rowsets + if (initialDestinations.isNonempty()) { + try (final ResettableWritableObjectChunk rowSetResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + initialDestinations.getRowSequenceIterator()) { + + // noinspection unchecked + final WritableObjectChunk rowSetBackingChunk = + rowSetResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); + + while (destinationsIterator.hasMore()) { + final long firstSliceDestination = destinationsIterator.peekNextKey(); + final long firstBackingChunkDestination = + rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); + + final long lastBackingChunkDestination = + firstBackingChunkDestination + rowSetBackingChunk.size() - 1; + final RowSequence initialDestinationsSlice = + destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); + + initialDestinationsSlice.forAllRowKeys((final long destination) -> { + final int backingChunkOffset = + Math.toIntExact(destination - firstBackingChunkDestination); + final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset)); + rowSets.set(destination, live ? addRowSet.toTracking() : addRowSet); + onReincarnated(destination); + }); + } + } + } + initialized = true; + } + + @Override + public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) { + // get the rowset for the updated items + final RowSet stepDestinations = stepUpdatedDestinations.build(); + + // use the builders to modify the rowsets + if (stepDestinations.isNonempty()) { + try (final ResettableWritableObjectChunk rowSetResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + stepDestinations.getRowSequenceIterator()) { + + // noinspection unchecked + final WritableObjectChunk rowSetBackingChunk = + rowSetResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk removedBuildersBackingChunk = + removedBuildersResettableChunk.asWritableObjectChunk(); + + while (destinationsIterator.hasMore()) { + final long firstSliceDestination = destinationsIterator.peekNextKey(); + final long firstBackingChunkDestination = + rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); + + final long lastBackingChunkDestination = + firstBackingChunkDestination + rowSetBackingChunk.size() - 1; + final RowSequence initialDestinationsSlice = + destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); + + initialDestinationsSlice.forAllRowKeys((final long destination) -> { + final int backingChunkOffset = + Math.toIntExact(destination - firstBackingChunkDestination); + try (final WritableRowSet addRowSet = + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); + final WritableRowSet removeRowSet = + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset))) { + final WritableRowSet workingRowSet = rowSetForSlot(backingChunkOffset); + + // process removes + final boolean wasNonEmpty = removeRowSet.isNonempty(); + workingRowSet.remove(removeRowSet); + if (wasNonEmpty && workingRowSet.isEmpty()) { + onEmptied(destination); + } + + // process adds + final boolean wasEmpty = workingRowSet.isEmpty(); + workingRowSet.insert(addRowSet); + if (wasEmpty && workingRowSet.isNonempty()) { + onReincarnated(destination); + } + } + }); + } + } + } initializeNewIndexPreviousValues(newDestinations); } From e1665c111eb680b7ec6f515ffcde04b218f42fa2 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 21 Sep 2022 13:40:55 -0700 Subject: [PATCH 16/25] WIP --- .../table/impl/by/GroupByChunkedOperator.java | 150 ++++++++---------- 1 file changed, 68 insertions(+), 82 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 93ff5d47c4e..c66f62185d0 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -14,7 +14,6 @@ import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; import io.deephaven.engine.rowset.chunkattributes.RowKeys; import io.deephaven.engine.table.*; -import io.deephaven.engine.table.impl.PrecomputedRowSetBuilderRandom; import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.sources.ObjectArraySource; import io.deephaven.engine.table.impl.sources.aggregate.AggregateColumnSource; @@ -43,14 +42,12 @@ public final class GroupByChunkedOperator private final ObjectArraySource rowSets; private final ObjectArraySource addedBuilders; private final ObjectArraySource removedBuilders; - private RowSetBuilderRandom stepUpdatedDestinations; - - private final ObjectArraySource modifiedBuilders; private final String[] inputColumnNames; private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; + private RowSetBuilderRandom stepUpdatedDestinationBuilder; private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; private boolean someKeyHasModifies; @@ -71,11 +68,9 @@ public final class GroupByChunkedOperator if (live) { resultInputsModifiedColumnSet = inputTable.newModifiedColumnSet(inputColumnNames); removedBuilders = new ObjectArraySource<>(Object.class); - modifiedBuilders = new ObjectArraySource<>(Object.class); } else { resultInputsModifiedColumnSet = null; removedBuilders = null; - modifiedBuilders = null; } initialized = false; } @@ -111,8 +106,7 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk indices, final in } else { accumulateToBuilderRandom(addedBuilders, indices, start, length, destination); } - if (stepUpdatedDestinations != null) { - stepUpdatedDestinations.addKey(destination); + if (stepUpdatedDestinationBuilder != null) { + stepUpdatedDestinationBuilder.addKey(destination); } } @@ -244,15 +238,15 @@ private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destinati } else { accumulateToBuilderRandom(addedBuilders, addRowSet, destination); } - if (stepUpdatedDestinations != null) { - stepUpdatedDestinations.addKey(destination); + if (stepUpdatedDestinationBuilder != null) { + stepUpdatedDestinationBuilder.addKey(destination); } } private void removeChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { accumulateToBuilderRandom(removedBuilders, indices, start, length, destination); - stepUpdatedDestinations.addKey(destination); + stepUpdatedDestinationBuilder.addKey(destination); } private void doShift(@NotNull final LongChunk preShiftRowKeys, @@ -352,22 +346,12 @@ private static WritableRowSet nullToEmpty(@Nullable final WritableRowSet rowSet) return rowSet == null ? RowSetFactory.empty() : rowSet; } - private WritableRowSet rowSetForSlot(final long destination) { - WritableRowSet rowSet = rowSets.getUnsafe(destination); - if (rowSet == null) { - final WritableRowSet empty = RowSetFactory.empty(); - rowSets.set(destination, rowSet = live ? empty.toTracking() : empty); - } - return rowSet; - } - @Override public void ensureCapacity(final long tableSize) { rowSets.ensureCapacity(tableSize); addedBuilders.ensureCapacity(tableSize); if (live) { removedBuilders.ensureCapacity(tableSize); - modifiedBuilders.ensureCapacity(tableSize); } } @@ -439,7 +423,7 @@ public ModifiedColumnSet apply(@NotNull final ModifiedColumnSet upstreamModified @Override public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - stepUpdatedDestinations = RowSetFactory.builderRandom(); + stepUpdatedDestinationBuilder = RowSetFactory.builderRandom(); stepValuesModified = upstream.modified().isNonempty() && upstream.modifiedColumnSet().nonempty() && upstream.modifiedColumnSet().containsAny(resultInputsModifiedColumnSet); someKeyHasAddsOrRemoves = false; @@ -482,7 +466,7 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { final int backingChunkOffset = Math.toIntExact(destination - firstBackingChunkDestination); final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset)); - rowSets.set(destination, live ? addRowSet.toTracking() : addRowSet); + rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); onReincarnated(destination); }); } @@ -494,67 +478,69 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { @Override public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) { // get the rowset for the updated items - final RowSet stepDestinations = stepUpdatedDestinations.build(); - - // use the builders to modify the rowsets - if (stepDestinations.isNonempty()) { - try (final ResettableWritableObjectChunk rowSetResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator destinationsIterator = - stepDestinations.getRowSequenceIterator()) { - - // noinspection unchecked - final WritableObjectChunk rowSetBackingChunk = - rowSetResettableChunk.asWritableObjectChunk(); - // noinspection unchecked - final WritableObjectChunk addedBuildersBackingChunk = - addedBuildersResettableChunk.asWritableObjectChunk(); - // noinspection unchecked - final WritableObjectChunk removedBuildersBackingChunk = - removedBuildersResettableChunk.asWritableObjectChunk(); - - while (destinationsIterator.hasMore()) { - final long firstSliceDestination = destinationsIterator.peekNextKey(); - final long firstBackingChunkDestination = - rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); - addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); - removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); - - final long lastBackingChunkDestination = - firstBackingChunkDestination + rowSetBackingChunk.size() - 1; - final RowSequence initialDestinationsSlice = - destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); - - initialDestinationsSlice.forAllRowKeys((final long destination) -> { - final int backingChunkOffset = - Math.toIntExact(destination - firstBackingChunkDestination); - try (final WritableRowSet addRowSet = - nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); - final WritableRowSet removeRowSet = - nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset))) { - final WritableRowSet workingRowSet = rowSetForSlot(backingChunkOffset); - - // process removes - final boolean wasNonEmpty = removeRowSet.isNonempty(); - workingRowSet.remove(removeRowSet); - if (wasNonEmpty && workingRowSet.isEmpty()) { - onEmptied(destination); - } - - // process adds - final boolean wasEmpty = workingRowSet.isEmpty(); - workingRowSet.insert(addRowSet); - if (wasEmpty && workingRowSet.isNonempty()) { + try (final WritableRowSet stepDestinations = stepUpdatedDestinationBuilder.build()) { + // use the builders to modify the rowsets + if (stepDestinations.isNonempty()) { + try (final ResettableWritableObjectChunk rowSetResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + stepDestinations.getRowSequenceIterator()) { + + // noinspection unchecked + final WritableObjectChunk rowSetBackingChunk = + rowSetResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk removedBuildersBackingChunk = + removedBuildersResettableChunk.asWritableObjectChunk(); + + while (destinationsIterator.hasMore()) { + final long firstSliceDestination = destinationsIterator.peekNextKey(); + final long firstBackingChunkDestination = + rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); + + final long lastBackingChunkDestination = + firstBackingChunkDestination + rowSetBackingChunk.size() - 1; + final RowSequence initialDestinationsSlice = + destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); + + initialDestinationsSlice.forAllRowKeys((final long destination) -> { + final int backingChunkOffset = + Math.toIntExact(destination - firstBackingChunkDestination); + WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); + if (workingRowSet == null) { + // use the addRowSet as the new rowset + final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); + rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); onReincarnated(destination); + } else { + try (final WritableRowSet addRowSet = + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); + final WritableRowSet removeRowSet = + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset))) { + final boolean wasEmpty = workingRowSet.isEmpty(); + workingRowSet.remove(removeRowSet); + workingRowSet.insert(addRowSet); + if (!wasEmpty && workingRowSet.isEmpty()) { + onEmptied(destination); + } else if (wasEmpty && workingRowSet.isNonempty()) { + onReincarnated(destination); + } + } } - } - }); + }); + } } } + stepUpdatedDestinationBuilder = null; } initializeNewIndexPreviousValues(newDestinations); } From c7340fe3f19e4198f417e39c348aee80e61cc44f Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Wed, 21 Sep 2022 15:42:03 -0700 Subject: [PATCH 17/25] COB WIP --- .../table/impl/by/FormulaChunkedOperator.java | 12 +- .../table/impl/by/GroupByChunkedOperator.java | 141 ++++++++---------- 2 files changed, 63 insertions(+), 90 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java index 0b5b64950ed..5917a3eb563 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java @@ -36,7 +36,7 @@ /** * An {@link IterativeChunkedAggregationOperator} used in the implementation of {@link Table#applyToAllBy}. */ -class FormulaChunkedOperator implements StateChangeRecorder, IterativeChunkedAggregationOperator { +class FormulaChunkedOperator implements IterativeChunkedAggregationOperator { private final GroupByChunkedOperator groupBy; private final boolean delegateToBy; @@ -101,16 +101,6 @@ class FormulaChunkedOperator implements StateChangeRecorder, IterativeChunkedAgg } } - @Override - public void startRecording(LongConsumer reincarnatedDestinationCallback, LongConsumer emptiedDestinationCallback) { - groupBy.startRecording(reincarnatedDestinationCallback, emptiedDestinationCallback); - } - - @Override - public void finishRecording() { - groupBy.finishRecording(); - } - @Override public void addChunk(final BucketedContext bucketedContext, final Chunk values, @NotNull final LongChunk inputRowKeys, diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index c66f62185d0..4adabb145ed 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -4,19 +4,21 @@ package io.deephaven.engine.table.impl.by; import io.deephaven.base.verify.Assert; -import io.deephaven.chunk.*; import io.deephaven.chunk.attributes.ChunkLengths; import io.deephaven.chunk.attributes.ChunkPositions; import io.deephaven.chunk.attributes.Values; import io.deephaven.datastructures.util.CollectionUtil; -import io.deephaven.engine.liveness.LivenessReferent; -import io.deephaven.engine.rowset.*; -import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; -import io.deephaven.engine.rowset.chunkattributes.RowKeys; +import io.deephaven.engine.rowset.RowSetFactory; import io.deephaven.engine.table.*; +import io.deephaven.engine.rowset.*; +import io.deephaven.engine.liveness.LivenessReferent; +import io.deephaven.engine.table.ModifiedColumnSet; import io.deephaven.engine.table.impl.QueryTable; import io.deephaven.engine.table.impl.sources.ObjectArraySource; import io.deephaven.engine.table.impl.sources.aggregate.AggregateColumnSource; +import io.deephaven.chunk.*; +import io.deephaven.engine.rowset.chunkattributes.OrderedRowKeys; +import io.deephaven.engine.rowset.chunkattributes.RowKeys; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -33,7 +35,6 @@ * {@link io.deephaven.api.agg.spec.AggSpecGroup}, and {@link io.deephaven.api.agg.Aggregation#AggGroup(String...)}. */ public final class GroupByChunkedOperator - extends BasicStateChangeRecorder implements IterativeChunkedAggregationOperator { private final QueryTable inputTable; @@ -47,14 +48,13 @@ public final class GroupByChunkedOperator private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; - private RowSetBuilderRandom stepUpdatedDestinationBuilder; private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; private boolean someKeyHasModifies; private boolean initialized; GroupByChunkedOperator(@NotNull final QueryTable inputTable, final boolean registeredWithHelper, - @NotNull final MatchPair... resultColumnPairs) { + @NotNull final MatchPair... resultColumnPairs) { this.inputTable = inputTable; this.registeredWithHelper = registeredWithHelper; live = inputTable.isRefreshing(); @@ -77,9 +77,9 @@ public final class GroupByChunkedOperator @Override public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= startPositions.size() > 0; // noinspection unchecked @@ -95,9 +95,9 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= startPositions.size() > 0; // noinspection unchecked @@ -113,21 +113,21 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public void shiftChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); // noinspection unchecked @@ -146,9 +146,9 @@ public void shiftChunk(final BucketedContext bucketedContext, final Chunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { if (!stepValuesModified) { return; } @@ -158,8 +158,8 @@ public void modifyRowKeys(final BucketedContext context, @Override public boolean addChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= chunkSize > 0; // noinspection unchecked @@ -176,8 +176,8 @@ public boolean addRowSet(SingletonContext context, RowSet rowSet, long destinati @Override public boolean removeChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= chunkSize > 0; // noinspection unchecked @@ -187,19 +187,19 @@ public boolean removeChunk(final SingletonContext singletonContext, final int ch @Override public boolean modifyChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk previousValues, final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk previousValues, final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public boolean shiftChunk(final SingletonContext singletonContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); // noinspection unchecked @@ -210,7 +210,7 @@ public boolean shiftChunk(final SingletonContext singletonContext, final Chunk rowKeys, - final long destination) { + final long destination) { if (!stepValuesModified) { return false; } @@ -219,16 +219,13 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long } private void addChunk(@NotNull final LongChunk indices, final int start, final int length, - final long destination) { + final long destination) { if (!initialized) { // during initialization, all rows are guaranteed to be in-order accumulateToBuilderSequential(addedBuilders, indices, start, length, destination); } else { accumulateToBuilderRandom(addedBuilders, indices, start, length, destination); } - if (stepUpdatedDestinationBuilder != null) { - stepUpdatedDestinationBuilder.addKey(destination); - } } private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destination) { @@ -238,35 +235,31 @@ private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destinati } else { accumulateToBuilderRandom(addedBuilders, addRowSet, destination); } - if (stepUpdatedDestinationBuilder != null) { - stepUpdatedDestinationBuilder.addKey(destination); - } } private void removeChunk(@NotNull final LongChunk indices, final int start, final int length, - final long destination) { + final long destination) { accumulateToBuilderRandom(removedBuilders, indices, start, length, destination); - stepUpdatedDestinationBuilder.addKey(destination); } private void doShift(@NotNull final LongChunk preShiftRowKeys, @NotNull final LongChunk postShiftRowKeys, - final int startPosition, final int runLength, final long destination) { + final int startPosition, final int runLength, final long destination) { // treat shift as remove + add removeChunk(preShiftRowKeys, startPosition, runLength, destination); addChunk(postShiftRowKeys, startPosition, runLength, destination); } private static void accumulateToBuilderSequential( - @NotNull final ObjectArraySource rowSetColumn, + @NotNull final ObjectArraySource builderColumn, @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { - final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); + final RowSetBuilderSequential builder = (RowSetBuilderSequential) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with these keys final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); newBuilder.appendOrderedRowKeysChunk(rowKeysToAdd, start, length); - rowSetColumn.set(destination, newBuilder); + builderColumn.set(destination, newBuilder); return; } // add the keys to the stored builder @@ -274,14 +267,14 @@ private static void accumulateToBuilderSequential( } private static void accumulateToBuilderSequential( - @NotNull final ObjectArraySource rowSetColumn, + @NotNull final ObjectArraySource builderColumn, @NotNull final RowSet rowSetToAdd, final long destination) { - final RowSetBuilderSequential builder = (RowSetBuilderSequential) rowSetColumn.getUnsafe(destination); + final RowSetBuilderSequential builder = (RowSetBuilderSequential) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with this rowset final RowSetBuilderSequential newBuilder = RowSetFactory.builderSequential(); newBuilder.appendRowSequence(rowSetToAdd); - rowSetColumn.set(destination, newBuilder); + builderColumn.set(destination, newBuilder); return; } // add the rowset to the stored builder @@ -289,29 +282,29 @@ private static void accumulateToBuilderSequential( } - private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource builderColumn, @NotNull final LongChunk rowKeysToAdd, final int start, final int length, final long destination) { - final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); + final RowSetBuilderRandom builder = (RowSetBuilderRandom) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with these keys final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); newBuilder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); - rowSetColumn.set(destination, newBuilder); + builderColumn.set(destination, newBuilder); return; } // add the keys to the stored builder builder.addOrderedRowKeysChunk(rowKeysToAdd, start, length); } - private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource rowSetColumn, + private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource builderColumn, @NotNull final RowSet rowSetToAdd, final long destination) { - final RowSetBuilderRandom builder = (RowSetBuilderRandom) rowSetColumn.getUnsafe(destination); + final RowSetBuilderRandom builder = (RowSetBuilderRandom) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with this rowset final RowSetBuilderRandom newBuilder = RowSetFactory.builderRandom(); newBuilder.addRowSet(rowSetToAdd); - rowSetColumn.set(destination, newBuilder); + builderColumn.set(destination, newBuilder); return; } // add the rowset to the stored builder @@ -337,8 +330,8 @@ private static WritableRowSet extractAndClearBuilderSequential( if (builder != null) { final WritableRowSet rowSet = builder.build(); builderChunk.set(offset, null); - return rowSet; - } + return rowSet; + } return null; } @@ -372,11 +365,11 @@ public void startTrackingPrevValues() { @Override public UnaryOperator initializeRefreshing(@NotNull final QueryTable resultTable, - @NotNull final LivenessReferent aggregationUpdateListener) { + @NotNull final LivenessReferent aggregationUpdateListener) { initializeNewIndexPreviousValues(resultTable.getRowSet()); return registeredWithHelper ? new InputToResultModifiedColumnSetFactory(resultTable, - resultColumns.keySet().toArray(CollectionUtil.ZERO_LENGTH_STRING_ARRAY)) + resultColumns.keySet().toArray(CollectionUtil.ZERO_LENGTH_STRING_ARRAY)) : null; } @@ -388,7 +381,7 @@ public UnaryOperator initializeRefreshing(@NotNull final Quer * @return The factory */ UnaryOperator makeInputToResultModifiedColumnSetFactory(@NotNull final QueryTable resultTable, - @NotNull final String[] resultColumnNames) { + @NotNull final String[] resultColumnNames) { return new InputToResultModifiedColumnSetFactory(resultTable, resultColumnNames); } @@ -399,7 +392,7 @@ private class InputToResultModifiedColumnSetFactory implements UnaryOperator rowSetResettableChunk = @@ -515,32 +506,24 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin initialDestinationsSlice.forAllRowKeys((final long destination) -> { final int backingChunkOffset = Math.toIntExact(destination - firstBackingChunkDestination); - WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); + final WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); if (workingRowSet == null) { // use the addRowSet as the new rowset final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); - onReincarnated(destination); } else { try (final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); final WritableRowSet removeRowSet = nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset))) { - final boolean wasEmpty = workingRowSet.isEmpty(); workingRowSet.remove(removeRowSet); workingRowSet.insert(addRowSet); - if (!wasEmpty && workingRowSet.isEmpty()) { - onEmptied(destination); - } else if (wasEmpty && workingRowSet.isNonempty()) { - onReincarnated(destination); - } } } }); } } } - stepUpdatedDestinationBuilder = null; } initializeNewIndexPreviousValues(newDestinations); } @@ -550,7 +533,7 @@ private void initializeNewIndexPreviousValues(@NotNull final RowSequence newDest return; } try (final ChunkSource.GetContext indicesGetContext = rowSets.makeGetContext(BLOCK_SIZE); - final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { + final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { while (newDestinationsIterator.hasMore()) { final long nextDestination = newDestinationsIterator.peekNextKey(); final long nextBlockEnd = (nextDestination / BLOCK_SIZE) * BLOCK_SIZE + BLOCK_SIZE - 1; From 5ddc31e89324fa03712c6b9d4ba71fb7e7d38031 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Thu, 22 Sep 2022 09:25:21 -0700 Subject: [PATCH 18/25] Aggregation Tests passing, still a little messy --- .../table/impl/by/AggregationContext.java | 17 +- .../BaseStreamFirstOrLastChunkedOperator.java | 3 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- .../by/ChunkedOperatorAggregationHelper.java | 19 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- .../table/impl/by/FormulaChunkedOperator.java | 10 +- .../table/impl/by/GroupByChunkedOperator.java | 206 ++++++++++-------- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- .../IterativeChunkedAggregationOperator.java | 10 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- .../impl/by/PartitionByChunkedOperator.java | 8 +- ...treamSortedFirstOrLastChunkedOperator.java | 6 +- .../impl/by/StreamFirstChunkedOperator.java | 2 +- .../impl/by/StreamLastChunkedOperator.java | 2 +- .../impl/by/TDigestPercentileOperator.java | 7 +- .../distinct/LongChunkedDistinctOperator.java | 1 - .../distinct/LongRollupDistinctOperator.java | 1 - .../unique/LongChunkedUniqueOperator.java | 1 - .../unique/LongRollupUniqueOperator.java | 1 - 22 files changed, 181 insertions(+), 155 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java index 711b2aae192..0866c1468b7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java @@ -234,10 +234,11 @@ ModifiedColumnSet[] getInputModifiedColumnSets(QueryTable input) { * initialization. * * @param resultTable The result {@link QueryTable} after initialization + * @param maxDestination The maximum destination slot created during initialization */ - void propagateInitialStateToOperators(@NotNull final QueryTable resultTable) { + void propagateInitialStateToOperators(@NotNull final QueryTable resultTable, final int maxDestination) { for (final IterativeChunkedAggregationOperator operator : operators) { - operator.propagateInitialState(resultTable); + operator.propagateInitialState(resultTable, maxDestination); } } @@ -269,10 +270,12 @@ UnaryOperator[] initializeRefreshing(@NotNull final QueryTabl * * @param upstream The upstream {@link TableUpdateImpl} * @param startingDestinationsCount The number of used destinations at the beginning of this step + * @param anyKeysModified Whether any grouping keys modified as a result of this update */ - void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, + boolean anyKeysModified) { for (final IterativeChunkedAggregationOperator operator : operators) { - operator.resetForStep(upstream, startingDestinationsCount); + operator.resetForStep(upstream, startingDestinationsCount, anyKeysModified); } } @@ -280,13 +283,15 @@ void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int starti * Allow all operators to perform any internal state keeping needed for destinations that were added (went from 0 * keys to > 0), removed (went from > 0 keys to 0), or modified (keys added or removed, or keys modified) by * this iteration. Note that the arguments to this method should not be mutated in any way. - * + * * @param downstream The downstream {@link TableUpdate} (which does not have its {@link ModifiedColumnSet} * finalized yet) * @param newDestinations New destinations added on this update + * @param anyKeysModified Whether any grouping keys were modified during this update */ void propagateChangesToOperators(@NotNull final TableUpdate downstream, - @NotNull final RowSet newDestinations) { + @NotNull final RowSet newDestinations, + final boolean anyKeysModified) { for (final IterativeChunkedAggregationOperator operator : operators) { operator.propagateUpdates(downstream, newDestinations); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java index 74e23ff35c2..3fa938255d2 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java @@ -95,7 +95,8 @@ public final boolean requiresRowKeys() { @Override @OverridingMethodsMustInvokeSuper - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, + boolean anyKeysModified) { if ((redirections = cachedRedirections.get()) == null) { cachedRedirections = new SoftReference<>(redirections = new LongArraySource()); ensureCapacity(startingDestinationsCount); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java index 2b67c7d4e17..a8309b17ae5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final ByteChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java index c993b44ee86..721de7cad37 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java @@ -53,8 +53,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -133,7 +133,7 @@ private boolean addChunk(@NotNull final CharChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index 280df34f166..8ed3e937ebf 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -219,7 +219,7 @@ private static QueryTable aggregation( // Construct the result table final QueryTable result = new QueryTable(resultRowSet, resultColumnSourceMap); - ac.propagateInitialStateToOperators(result); + ac.propagateInitialStateToOperators(result, outputPosition.intValue()); if (input.isRefreshing()) { assert keyColumnsCopied != null; @@ -563,7 +563,7 @@ private TableUpdate computeDownstreamIndicesAndCopyKeys( @NotNull final ModifiedColumnSet resultModifiedColumnSet, @NotNull final UnaryOperator[] resultModifiedColumnSetFactories) { final int firstStateToAdd = outputPosition.intValue(); - ac.resetOperatorsForStep(upstream, firstStateToAdd); + ac.resetOperatorsForStep(upstream, firstStateToAdd, keysModified); if (upstream.removed().isNonempty()) { doRemoves(upstream.removed()); @@ -678,7 +678,7 @@ private TableUpdate computeDownstreamIndicesAndCopyKeys( downstream.modified().writableCast().remove(downstream.removed()); } - ac.propagateChangesToOperators(downstream, newStates); + ac.propagateChangesToOperators(downstream, newStates, keysModified); } extractDownstreamModifiedColumnSet(downstream, resultModifiedColumnSet, modifiedOperators, @@ -1593,7 +1593,7 @@ private static QueryTable staticGroupedAggregation(QueryTable withView, String k final QueryTable result = new QueryTable(RowSetFactory.flat(responsiveGroups).toTracking(), resultColumnSourceMap); - ac.propagateInitialStateToOperators(result); + ac.propagateInitialStateToOperators(result, responsiveGroups); final ReverseLookupListener rll = ReverseLookupListener.makeReverseLookupListenerWithSnapshot(result, keyName); ac.setReverseLookupFunction(k -> (int) rll.get(k)); @@ -1957,7 +1957,8 @@ private static QueryTable noKeyAggregation( final QueryTable result = new QueryTable(RowSetFactory.flat(initialResultSize).toTracking(), resultColumnSourceMap); - ac.propagateInitialStateToOperators(result); + // always will create one result for zerokey + ac.propagateInitialStateToOperators(result, 1); if (table.isRefreshing()) { ac.startTrackingPrevValues(); @@ -1983,7 +1984,7 @@ public void onUpdate(@NotNull final TableUpdate upstream) { } private void processNoKeyUpdate(@NotNull final TableUpdate upstream) { - ac.resetOperatorsForStep(upstream, 1); + ac.resetOperatorsForStep(upstream, 1, false); final ModifiedColumnSet upstreamModifiedColumnSet = upstream.modified().isEmpty() ? ModifiedColumnSet.EMPTY @@ -2095,7 +2096,7 @@ private void processNoKeyUpdate(@NotNull final TableUpdate upstream) { final int newStatesCreated = Math.max(statesCreated, newResultSize); try (final RowSet newStates = makeNewStatesRowSet(statesCreated, newStatesCreated - 1)) { - ac.propagateChangesToOperators(downstream, newStates); + ac.propagateChangesToOperators(downstream, newStates, false); } statesCreated = newStatesCreated; @@ -2412,7 +2413,7 @@ public void addRange(final long firstRowKey, final long lastRowKey) { * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key * for the builder to the maximum output position without loss of fidelity. */ - private static class BitmapRandomBuilder implements RowSetBuilderRandom { + public static class BitmapRandomBuilder implements RowSetBuilderRandom { /** * An upper bound on {@code lastUsed}. That is, the highest bit index that may be used in {@code bitset}. @@ -2434,7 +2435,7 @@ private static class BitmapRandomBuilder implements RowSetBuilderRandom { */ long[] bitset; - private BitmapRandomBuilder(int maxKey) { + public BitmapRandomBuilder(int maxKey) { this.maxKey = maxKey; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java index 5598e6b07e7..c283412eb31 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final DoubleChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java index bd9171b5954..7fab137ef9a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final FloatChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java index 5917a3eb563..9e1dfbabef9 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java @@ -28,7 +28,6 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import java.util.function.LongConsumer; import java.util.function.UnaryOperator; import static io.deephaven.engine.table.impl.sources.ArrayBackedColumnSource.BLOCK_SIZE; @@ -247,9 +246,9 @@ public void ensureCapacity(final long tableSize) { } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { if (delegateToBy) { - groupBy.propagateInitialState(resultTable); + groupBy.propagateInitialState(resultTable, startingDestinationsCount); } final Map> byResultColumns = groupBy.getResultColumns(); @@ -298,9 +297,10 @@ public UnaryOperator initializeRefreshing(@NotNull final Quer } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, + boolean anyKeysModified) { if (delegateToBy) { - groupBy.resetForStep(upstream, startingDestinationsCount); + groupBy.resetForStep(upstream, startingDestinationsCount, anyKeysModified); } updateUpstreamModifiedColumnSet = upstream.modified().isEmpty() ? ModifiedColumnSet.EMPTY : upstream.modifiedColumnSet(); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 4adabb145ed..4a046532db8 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -48,13 +48,16 @@ public final class GroupByChunkedOperator private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; + private ChunkedOperatorAggregationHelper.BitmapRandomBuilder stepDestinationsModified; + private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; private boolean someKeyHasModifies; + private boolean groupKeyModified; private boolean initialized; GroupByChunkedOperator(@NotNull final QueryTable inputTable, final boolean registeredWithHelper, - @NotNull final MatchPair... resultColumnPairs) { + @NotNull final MatchPair... resultColumnPairs) { this.inputTable = inputTable; this.registeredWithHelper = registeredWithHelper; live = inputTable.isRefreshing(); @@ -77,9 +80,9 @@ public final class GroupByChunkedOperator @Override public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= startPositions.size() > 0; // noinspection unchecked @@ -95,9 +98,9 @@ public void addChunk(final BucketedContext bucketedContext, final Chunk values, - @NotNull final LongChunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= startPositions.size() > 0; // noinspection unchecked @@ -113,21 +116,21 @@ public void removeChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public void shiftChunk(final BucketedContext bucketedContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); // noinspection unchecked @@ -146,9 +149,9 @@ public void shiftChunk(final BucketedContext bucketedContext, final Chunk inputRowKeys, - @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, - @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { + @NotNull final LongChunk inputRowKeys, + @NotNull final IntChunk destinations, @NotNull final IntChunk startPositions, + @NotNull final IntChunk length, @NotNull final WritableBooleanChunk stateModified) { if (!stepValuesModified) { return; } @@ -158,8 +161,8 @@ public void modifyRowKeys(final BucketedContext context, @Override public boolean addChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= chunkSize > 0; // noinspection unchecked @@ -176,8 +179,8 @@ public boolean addRowSet(SingletonContext context, RowSet rowSet, long destinati @Override public boolean removeChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk values, - @NotNull final LongChunk inputRowKeys, final long destination) { + final Chunk values, + @NotNull final LongChunk inputRowKeys, final long destination) { Assert.eqNull(values, "values"); someKeyHasAddsOrRemoves |= chunkSize > 0; // noinspection unchecked @@ -187,19 +190,19 @@ public boolean removeChunk(final SingletonContext singletonContext, final int ch @Override public boolean modifyChunk(final SingletonContext singletonContext, final int chunkSize, - final Chunk previousValues, final Chunk newValues, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk previousValues, final Chunk newValues, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { // We have no inputs, so we should never get here. throw new IllegalStateException(); } @Override public boolean shiftChunk(final SingletonContext singletonContext, final Chunk previousValues, - final Chunk newValues, - @NotNull final LongChunk preShiftRowKeys, - @NotNull final LongChunk postShiftRowKeys, - final long destination) { + final Chunk newValues, + @NotNull final LongChunk preShiftRowKeys, + @NotNull final LongChunk postShiftRowKeys, + final long destination) { Assert.eqNull(previousValues, "previousValues"); Assert.eqNull(newValues, "newValues"); // noinspection unchecked @@ -210,7 +213,7 @@ public boolean shiftChunk(final SingletonContext singletonContext, final Chunk rowKeys, - final long destination) { + final long destination) { if (!stepValuesModified) { return false; } @@ -219,13 +222,16 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long } private void addChunk(@NotNull final LongChunk indices, final int start, final int length, - final long destination) { + final long destination) { if (!initialized) { // during initialization, all rows are guaranteed to be in-order accumulateToBuilderSequential(addedBuilders, indices, start, length, destination); } else { accumulateToBuilderRandom(addedBuilders, indices, start, length, destination); } + if (stepDestinationsModified != null) { + stepDestinationsModified.addKey(destination); + } } private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destination) { @@ -238,13 +244,14 @@ private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destinati } private void removeChunk(@NotNull final LongChunk indices, final int start, final int length, - final long destination) { + final long destination) { accumulateToBuilderRandom(removedBuilders, indices, start, length, destination); + stepDestinationsModified.addKey(destination); } private void doShift(@NotNull final LongChunk preShiftRowKeys, @NotNull final LongChunk postShiftRowKeys, - final int startPosition, final int runLength, final long destination) { + final int startPosition, final int runLength, final long destination) { // treat shift as remove + add removeChunk(preShiftRowKeys, startPosition, runLength, destination); addChunk(postShiftRowKeys, startPosition, runLength, destination); @@ -283,8 +290,8 @@ private static void accumulateToBuilderSequential( private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource builderColumn, - @NotNull final LongChunk rowKeysToAdd, - final int start, final int length, final long destination) { + @NotNull final LongChunk rowKeysToAdd, + final int start, final int length, final long destination) { final RowSetBuilderRandom builder = (RowSetBuilderRandom) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with these keys @@ -298,7 +305,7 @@ private static void accumulateToBuilderRandom(@NotNull final ObjectArraySource builderColumn, - @NotNull final RowSet rowSetToAdd, final long destination) { + @NotNull final RowSet rowSetToAdd, final long destination) { final RowSetBuilderRandom builder = (RowSetBuilderRandom) builderColumn.getUnsafe(destination); if (builder == null) { // create (and store) a new builder, fill with this rowset @@ -330,8 +337,8 @@ private static WritableRowSet extractAndClearBuilderSequential( if (builder != null) { final WritableRowSet rowSet = builder.build(); builderChunk.set(offset, null); - return rowSet; - } + return rowSet; + } return null; } @@ -365,11 +372,11 @@ public void startTrackingPrevValues() { @Override public UnaryOperator initializeRefreshing(@NotNull final QueryTable resultTable, - @NotNull final LivenessReferent aggregationUpdateListener) { + @NotNull final LivenessReferent aggregationUpdateListener) { initializeNewIndexPreviousValues(resultTable.getRowSet()); return registeredWithHelper ? new InputToResultModifiedColumnSetFactory(resultTable, - resultColumns.keySet().toArray(CollectionUtil.ZERO_LENGTH_STRING_ARRAY)) + resultColumns.keySet().toArray(CollectionUtil.ZERO_LENGTH_STRING_ARRAY)) : null; } @@ -381,7 +388,7 @@ public UnaryOperator initializeRefreshing(@NotNull final Quer * @return The factory */ UnaryOperator makeInputToResultModifiedColumnSetFactory(@NotNull final QueryTable resultTable, - @NotNull final String[] resultColumnNames) { + @NotNull final String[] resultColumnNames) { return new InputToResultModifiedColumnSetFactory(resultTable, resultColumnNames); } @@ -392,7 +399,7 @@ private class InputToResultModifiedColumnSetFactory implements UnaryOperator rowSetResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator destinationsIterator = - initialDestinations.getRowSequenceIterator()) { - - // noinspection unchecked - final WritableObjectChunk rowSetBackingChunk = - rowSetResettableChunk.asWritableObjectChunk(); - // noinspection unchecked - final WritableObjectChunk addedBuildersBackingChunk = - addedBuildersResettableChunk.asWritableObjectChunk(); - - while (destinationsIterator.hasMore()) { - final long firstSliceDestination = destinationsIterator.peekNextKey(); - final long firstBackingChunkDestination = - rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); - addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); - - final long lastBackingChunkDestination = - firstBackingChunkDestination + rowSetBackingChunk.size() - 1; - final RowSequence initialDestinationsSlice = - destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); - - initialDestinationsSlice.forAllRowKeys((final long destination) -> { - final int backingChunkOffset = - Math.toIntExact(destination - firstBackingChunkDestination); - final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset)); - rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); - }); - } + try (final RowSet initialDestinations = RowSetFactory.flat(startingDestinationsCount); + final ResettableWritableObjectChunk rowSetResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + initialDestinations.getRowSequenceIterator()) { + + // noinspection unchecked + final WritableObjectChunk rowSetBackingChunk = + rowSetResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); + + while (destinationsIterator.hasMore()) { + final long firstSliceDestination = destinationsIterator.peekNextKey(); + final long firstBackingChunkDestination = + rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); + + final long lastBackingChunkDestination = + firstBackingChunkDestination + rowSetBackingChunk.size() - 1; + final RowSequence initialDestinationsSlice = + destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); + + initialDestinationsSlice.forAllRowKeys((final long destination) -> { + final int backingChunkOffset = + Math.toIntExact(destination - firstBackingChunkDestination); + final WritableRowSet addRowSet = nullToEmpty( + extractAndClearBuilderSequential(addedBuildersBackingChunk, backingChunkOffset)); + rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); + }); } } initialized = true; @@ -469,17 +478,20 @@ public void propagateInitialState(@NotNull final QueryTable resultTable) { @Override public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) { // get the rowset for the updated items - try (final WritableRowSet stepDestinations = downstream.added().union(downstream.removed())) { + try (final WritableRowSet stepDestinations = stepDestinationsModified.build()) { + // add the new destinations as well + stepDestinations.insert(newDestinations); + // use the builders to modify the rowsets if (stepDestinations.isNonempty()) { try (final ResettableWritableObjectChunk rowSetResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator destinationsIterator = - stepDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + stepDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk rowSetBackingChunk = @@ -495,8 +507,10 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin final long firstSliceDestination = destinationsIterator.peekNextKey(); final long firstBackingChunkDestination = rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); - addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, firstSliceDestination); - removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, + firstSliceDestination); + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, + firstSliceDestination); final long lastBackingChunkDestination = firstBackingChunkDestination + rowSetBackingChunk.size() - 1; @@ -509,13 +523,16 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin final WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); if (workingRowSet == null) { // use the addRowSet as the new rowset - final WritableRowSet addRowSet = nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); + final WritableRowSet addRowSet = nullToEmpty( + extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); } else { try (final WritableRowSet addRowSet = - nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); - final WritableRowSet removeRowSet = - nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, backingChunkOffset))) { + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, + backingChunkOffset)); + final WritableRowSet removeRowSet = + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, + backingChunkOffset))) { workingRowSet.remove(removeRowSet); workingRowSet.insert(addRowSet); } @@ -524,6 +541,7 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin } } } + stepDestinationsModified = null; } initializeNewIndexPreviousValues(newDestinations); } @@ -533,7 +551,7 @@ private void initializeNewIndexPreviousValues(@NotNull final RowSequence newDest return; } try (final ChunkSource.GetContext indicesGetContext = rowSets.makeGetContext(BLOCK_SIZE); - final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { + final RowSequence.Iterator newDestinationsIterator = newDestinations.getRowSequenceIterator()) { while (newDestinationsIterator.hasMore()) { final long nextDestination = newDestinationsIterator.peekNextKey(); final long nextBlockEnd = (nextDestination / BLOCK_SIZE) * BLOCK_SIZE + BLOCK_SIZE - 1; diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java index c3abd87b3a7..21d2ce8aa8b 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final IntChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java index 3baad4f4be6..751f7e631a7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java @@ -275,8 +275,9 @@ default boolean addRowSet(SingletonContext context, RowSet rowSet, long destinat * Perform any internal state keeping needed for destinations that were added during initialization. * * @param resultTable The result {@link QueryTable} after initialization + * @param startingDestinationsCount The number of used destinations at the beginning of this step */ - default void propagateInitialState(@NotNull final QueryTable resultTable) {} + default void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) {} /** * Called after initialization; when the operator's result columns must have previous tracking enabled. @@ -301,17 +302,18 @@ default UnaryOperator initializeRefreshing(@NotNull final Que /** * Reset any per-step internal state. Note that the arguments to this method should not be mutated in any way. - * + * * @param upstream The upstream ShiftAwareListener.Update * @param startingDestinationsCount The number of used destinations at the beginning of this step + * @param anyKeysModified Whether any grouping keys modified as a result of this update */ - default void resetForStep(@NotNull TableUpdate upstream, int startingDestinationsCount) {} + default void resetForStep(@NotNull TableUpdate upstream, int startingDestinationsCount, boolean anyKeysModified) {} /** * Perform any internal state keeping needed for destinations that were added (went from 0 keys to > 0), removed * (went from > 0 keys to 0), or modified (keys added or removed, or keys modified) by this iteration. Note that * the arguments to this method should not be mutated in any way. - * + * * @param downstream The downstream TableUpdate (which does not have its {@link ModifiedColumnSet} * finalized yet) * @param newDestinations New destinations added on this update diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java index 0434a9023e7..05f7bf74763 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final LongChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java index 0ae2bf8270a..242be9a7cfc 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final ObjectChunk va } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index e12f155c060..dd453454eb6 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -113,7 +113,8 @@ public interface AttributeCopier { * downstream modifies, because updates to constituents are not modifies to their rows in the aggregation * output table, but rather table updates to be propagated. *

- * This exists in each cycle between {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int)} and + * This exists in each cycle between + * {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int, boolean)} and * {@link IterativeChunkedAggregationOperator#propagateUpdates(TableUpdate, RowSet)} *

* If this ever becomes necessary in other operators, it could be moved out to the helper the way modified @@ -529,7 +530,7 @@ public void ensureCapacity(final long tableSize) { public void startTrackingPrevValues() {} @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { Assert.neqTrue(initialized, "initialized"); final RowSet initialDestinations = resultTable.getRowSet(); if (initialDestinations.isNonempty()) { @@ -610,7 +611,8 @@ private void linkTableReferences(@NotNull final Table subTable) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, int startingDestinationsCount) { + public void resetForStep(@NotNull final TableUpdate upstream, int startingDestinationsCount, + boolean anyKeysModified) { stepUpdatedDestinations = RowSetFactory.empty(); final boolean upstreamModified = upstream.modified().isNonempty() && upstream.modifiedColumnSet().nonempty(); if (upstreamModified) { diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java index 76bc6b23a25..5787712b733 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { - super.resetForStep(upstream, startingDestinationsCount); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { + super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } @@ -138,7 +138,7 @@ private boolean addChunk(@NotNull final ShortChunk values, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamFirstChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamFirstChunkedOperator.java index 1e090e089da..bd5d0ab77a5 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamFirstChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamFirstChunkedOperator.java @@ -149,7 +149,7 @@ private boolean maybeAssignFirst(final long destination, final long sourceIndexK } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; Assert.eq(resultTable.size(), "resultTable.size()", nextDestination, "nextDestination"); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamLastChunkedOperator.java index b37fef1356a..8363824d2af 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/StreamLastChunkedOperator.java @@ -75,7 +75,7 @@ public boolean addRowSet(final SingletonContext context, } @Override - public void propagateInitialState(@NotNull final QueryTable resultTable) { + public void propagateInitialState(@NotNull final QueryTable resultTable, int startingDestinationsCount) { copyStreamToResult(resultTable.getRowSet()); redirections = null; } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java index e3baa25cd91..7ffd2b9a4e4 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java @@ -184,7 +184,7 @@ public boolean modifyChunk(SingletonContext context, int chunkSize, Chunk Date: Thu, 22 Sep 2022 09:35:02 -0700 Subject: [PATCH 19/25] cleaned up a bit, tests still passing --- .../engine/table/impl/by/GroupByChunkedOperator.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 4a046532db8..e69b9141239 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -53,7 +53,6 @@ public final class GroupByChunkedOperator private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; private boolean someKeyHasModifies; - private boolean groupKeyModified; private boolean initialized; GroupByChunkedOperator(@NotNull final QueryTable inputTable, final boolean registeredWithHelper, @@ -428,7 +427,6 @@ public void resetForStep(@NotNull final TableUpdate upstream, final int starting && upstream.modifiedColumnSet().containsAny(resultInputsModifiedColumnSet); someKeyHasAddsOrRemoves = false; someKeyHasModifies = false; - groupKeyModified = anyKeysModified; stepDestinationsModified = new ChunkedOperatorAggregationHelper.BitmapRandomBuilder(startingDestinationsCount); } @@ -479,7 +477,8 @@ public void propagateInitialState(@NotNull final QueryTable resultTable, int sta public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) { // get the rowset for the updated items try (final WritableRowSet stepDestinations = stepDestinationsModified.build()) { - // add the new destinations as well + + // add the new destinations so a rowset will get created if it doesn't exist stepDestinations.insert(newDestinations); // use the builders to modify the rowsets From efc51861216287e8ab5aa56e57a72594569410bb Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Thu, 22 Sep 2022 09:52:52 -0700 Subject: [PATCH 20/25] removed anyKeysModified from propagateUpdates() in chunked aggregation --- .../deephaven/engine/table/impl/by/AggregationContext.java | 6 ++---- .../table/impl/by/ChunkedOperatorAggregationHelper.java | 4 ++-- .../table/impl/by/IterativeChunkedAggregationOperator.java | 3 ++- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java index 0866c1468b7..f4b770f028c 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java @@ -270,7 +270,7 @@ UnaryOperator[] initializeRefreshing(@NotNull final QueryTabl * * @param upstream The upstream {@link TableUpdateImpl} * @param startingDestinationsCount The number of used destinations at the beginning of this step - * @param anyKeysModified Whether any grouping keys modified as a result of this update + * @param anyKeysModified Whether any grouping keys were modified during this update */ void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { @@ -287,11 +287,9 @@ void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int starti * @param downstream The downstream {@link TableUpdate} (which does not have its {@link ModifiedColumnSet} * finalized yet) * @param newDestinations New destinations added on this update - * @param anyKeysModified Whether any grouping keys were modified during this update */ void propagateChangesToOperators(@NotNull final TableUpdate downstream, - @NotNull final RowSet newDestinations, - final boolean anyKeysModified) { + @NotNull final RowSet newDestinations) { for (final IterativeChunkedAggregationOperator operator : operators) { operator.propagateUpdates(downstream, newDestinations); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index 8ed3e937ebf..d6a16be1a90 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -678,7 +678,7 @@ private TableUpdate computeDownstreamIndicesAndCopyKeys( downstream.modified().writableCast().remove(downstream.removed()); } - ac.propagateChangesToOperators(downstream, newStates, keysModified); + ac.propagateChangesToOperators(downstream, newStates); } extractDownstreamModifiedColumnSet(downstream, resultModifiedColumnSet, modifiedOperators, @@ -2096,7 +2096,7 @@ private void processNoKeyUpdate(@NotNull final TableUpdate upstream) { final int newStatesCreated = Math.max(statesCreated, newResultSize); try (final RowSet newStates = makeNewStatesRowSet(statesCreated, newStatesCreated - 1)) { - ac.propagateChangesToOperators(downstream, newStates, false); + ac.propagateChangesToOperators(downstream, newStates); } statesCreated = newStatesCreated; diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java index 751f7e631a7..2953eec9e52 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java @@ -313,10 +313,11 @@ default void resetForStep(@NotNull TableUpdate upstream, int startingDestination * Perform any internal state keeping needed for destinations that were added (went from 0 keys to > 0), removed * (went from > 0 keys to 0), or modified (keys added or removed, or keys modified) by this iteration. Note that * the arguments to this method should not be mutated in any way. - * + * * @param downstream The downstream TableUpdate (which does not have its {@link ModifiedColumnSet} * finalized yet) * @param newDestinations New destinations added on this update + * */ default void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) {} From 1452d4ff7f10d9223c6b0d4407aef6beeb49960f Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Thu, 22 Sep 2022 10:58:45 -0700 Subject: [PATCH 21/25] revert changes to resetForStep --- .../engine/table/impl/by/AggregationContext.java | 9 +++------ .../by/BaseStreamFirstOrLastChunkedOperator.java | 3 +-- .../ByteStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../CharStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../impl/by/ChunkedOperatorAggregationHelper.java | 4 ++-- ...oubleStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- ...FloatStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../table/impl/by/FormulaChunkedOperator.java | 5 ++--- .../table/impl/by/GroupByChunkedOperator.java | 13 ++++++++++--- .../IntStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../by/IterativeChunkedAggregationOperator.java | 6 ++---- .../LongStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- ...bjectStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../table/impl/by/PartitionByChunkedOperator.java | 5 ++--- ...ShortStreamSortedFirstOrLastChunkedOperator.java | 4 ++-- .../table/impl/by/TDigestPercentileOperator.java | 3 +-- 16 files changed, 39 insertions(+), 41 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java index f4b770f028c..7a4f6dd0612 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java @@ -267,15 +267,12 @@ UnaryOperator[] initializeRefreshing(@NotNull final QueryTabl /** * Allow all operators to reset any per-step internal state. Note that the arguments to this method should not be * mutated in any way. - * - * @param upstream The upstream {@link TableUpdateImpl} + * @param upstream The upstream {@link TableUpdateImpl} * @param startingDestinationsCount The number of used destinations at the beginning of this step - * @param anyKeysModified Whether any grouping keys were modified during this update */ - void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, - boolean anyKeysModified) { + void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { for (final IterativeChunkedAggregationOperator operator : operators) { - operator.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + operator.resetForStep(upstream, startingDestinationsCount); } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java index 3fa938255d2..74e23ff35c2 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BaseStreamFirstOrLastChunkedOperator.java @@ -95,8 +95,7 @@ public final boolean requiresRowKeys() { @Override @OverridingMethodsMustInvokeSuper - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, - boolean anyKeysModified) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { if ((redirections = cachedRedirections.get()) == null) { cachedRedirections = new SoftReference<>(redirections = new LongArraySource()); ensureCapacity(startingDestinationsCount); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java index a8309b17ae5..923dfded2a6 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ByteStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java index 721de7cad37..e8fa4672a25 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/CharStreamSortedFirstOrLastChunkedOperator.java @@ -53,8 +53,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index d6a16be1a90..1aad376e62e 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -563,7 +563,7 @@ private TableUpdate computeDownstreamIndicesAndCopyKeys( @NotNull final ModifiedColumnSet resultModifiedColumnSet, @NotNull final UnaryOperator[] resultModifiedColumnSetFactories) { final int firstStateToAdd = outputPosition.intValue(); - ac.resetOperatorsForStep(upstream, firstStateToAdd, keysModified); + ac.resetOperatorsForStep(upstream, firstStateToAdd); if (upstream.removed().isNonempty()) { doRemoves(upstream.removed()); @@ -1984,7 +1984,7 @@ public void onUpdate(@NotNull final TableUpdate upstream) { } private void processNoKeyUpdate(@NotNull final TableUpdate upstream) { - ac.resetOperatorsForStep(upstream, 1, false); + ac.resetOperatorsForStep(upstream, 1); final ModifiedColumnSet upstreamModifiedColumnSet = upstream.modified().isEmpty() ? ModifiedColumnSet.EMPTY diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java index c283412eb31..4410267e9a9 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/DoubleStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java index 7fab137ef9a..a6834cbc9ea 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FloatStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java index 9e1dfbabef9..203d8eb6451 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/FormulaChunkedOperator.java @@ -297,10 +297,9 @@ public UnaryOperator initializeRefreshing(@NotNull final Quer } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, - boolean anyKeysModified) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { if (delegateToBy) { - groupBy.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + groupBy.resetForStep(upstream, startingDestinationsCount); } updateUpstreamModifiedColumnSet = upstream.modified().isEmpty() ? ModifiedColumnSet.EMPTY : upstream.modifiedColumnSet(); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index e69b9141239..497599ea4b3 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -222,6 +222,9 @@ public boolean modifyRowKeys(final SingletonContext context, @NotNull final Long private void addChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { + if (length == 0) { + return; + } if (!initialized) { // during initialization, all rows are guaranteed to be in-order accumulateToBuilderSequential(addedBuilders, indices, start, length, destination); @@ -234,6 +237,9 @@ private void addChunk(@NotNull final LongChunk indices, final in } private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destination) { + if (addRowSet.isEmpty()) { + return; + } if (!initialized) { // during initialization, all rows are guaranteed to be in-order accumulateToBuilderSequential(addedBuilders, addRowSet, destination); @@ -244,6 +250,9 @@ private void addRowsToSlot(@NotNull final RowSet addRowSet, final long destinati private void removeChunk(@NotNull final LongChunk indices, final int start, final int length, final long destination) { + if (length == 0) { + return; + } accumulateToBuilderRandom(removedBuilders, indices, start, length, destination); stepDestinationsModified.addKey(destination); } @@ -421,8 +430,7 @@ public ModifiedColumnSet apply(@NotNull final ModifiedColumnSet upstreamModified } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, - boolean anyKeysModified) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { stepValuesModified = upstream.modified().isNonempty() && upstream.modifiedColumnSet().nonempty() && upstream.modifiedColumnSet().containsAny(resultInputsModifiedColumnSet); someKeyHasAddsOrRemoves = false; @@ -477,7 +485,6 @@ public void propagateInitialState(@NotNull final QueryTable resultTable, int sta public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull final RowSet newDestinations) { // get the rowset for the updated items try (final WritableRowSet stepDestinations = stepDestinationsModified.build()) { - // add the new destinations so a rowset will get created if it doesn't exist stepDestinations.insert(newDestinations); diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java index 21d2ce8aa8b..206055bf83a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IntStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java index 2953eec9e52..d4b12d2bac0 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java @@ -302,12 +302,10 @@ default UnaryOperator initializeRefreshing(@NotNull final Que /** * Reset any per-step internal state. Note that the arguments to this method should not be mutated in any way. - * - * @param upstream The upstream ShiftAwareListener.Update + * @param upstream The upstream ShiftAwareListener.Update * @param startingDestinationsCount The number of used destinations at the beginning of this step - * @param anyKeysModified Whether any grouping keys modified as a result of this update */ - default void resetForStep(@NotNull TableUpdate upstream, int startingDestinationsCount, boolean anyKeysModified) {} + default void resetForStep(@NotNull TableUpdate upstream, int startingDestinationsCount) {} /** * Perform any internal state keeping needed for destinations that were added (went from 0 keys to > 0), removed diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java index 05f7bf74763..3a457850f1a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/LongStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java index 242be9a7cfc..b1d164da2df 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ObjectStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index dd453454eb6..eed1427dcdb 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -114,7 +114,7 @@ public interface AttributeCopier { * output table, but rather table updates to be propagated. *

* This exists in each cycle between - * {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int, boolean)} and + * {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int)} and * {@link IterativeChunkedAggregationOperator#propagateUpdates(TableUpdate, RowSet)} *

* If this ever becomes necessary in other operators, it could be moved out to the helper the way modified @@ -611,8 +611,7 @@ private void linkTableReferences(@NotNull final Table subTable) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, int startingDestinationsCount, - boolean anyKeysModified) { + public void resetForStep(@NotNull final TableUpdate upstream, int startingDestinationsCount) { stepUpdatedDestinations = RowSetFactory.empty(); final boolean upstreamModified = upstream.modified().isNonempty() && upstream.modifiedColumnSet().nonempty(); if (upstreamModified) { diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java index 5787712b733..305a6d189fe 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ShortStreamSortedFirstOrLastChunkedOperator.java @@ -58,8 +58,8 @@ public void ensureCapacity(final long tableSize) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, boolean anyKeysModified) { - super.resetForStep(upstream, startingDestinationsCount, anyKeysModified); + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { + super.resetForStep(upstream, startingDestinationsCount); if (isCombo) { changedDestinationsBuilder = RowSetFactory.builderRandom(); } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java index 7ffd2b9a4e4..a24475410e7 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/TDigestPercentileOperator.java @@ -200,8 +200,7 @@ private void updateDestination(final long destination) { } @Override - public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount, - boolean anyKeysModified) { + public void resetForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { modifiedThisStep = false; } From 6cf93746aa30839875ed7467797afbb25ba68ef2 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Thu, 22 Sep 2022 11:12:49 -0700 Subject: [PATCH 22/25] spotless for the win --- .../io/deephaven/engine/table/impl/by/AggregationContext.java | 3 ++- .../table/impl/by/IterativeChunkedAggregationOperator.java | 3 ++- .../engine/table/impl/by/PartitionByChunkedOperator.java | 3 +-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java index 7a4f6dd0612..657e1471a0f 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java @@ -267,7 +267,8 @@ UnaryOperator[] initializeRefreshing(@NotNull final QueryTabl /** * Allow all operators to reset any per-step internal state. Note that the arguments to this method should not be * mutated in any way. - * @param upstream The upstream {@link TableUpdateImpl} + * + * @param upstream The upstream {@link TableUpdateImpl} * @param startingDestinationsCount The number of used destinations at the beginning of this step */ void resetOperatorsForStep(@NotNull final TableUpdate upstream, final int startingDestinationsCount) { diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java index d4b12d2bac0..13cad9b5b51 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/IterativeChunkedAggregationOperator.java @@ -302,7 +302,8 @@ default UnaryOperator initializeRefreshing(@NotNull final Que /** * Reset any per-step internal state. Note that the arguments to this method should not be mutated in any way. - * @param upstream The upstream ShiftAwareListener.Update + * + * @param upstream The upstream ShiftAwareListener.Update * @param startingDestinationsCount The number of used destinations at the beginning of this step */ default void resetForStep(@NotNull TableUpdate upstream, int startingDestinationsCount) {} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java index eed1427dcdb..43f448ae049 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/PartitionByChunkedOperator.java @@ -113,8 +113,7 @@ public interface AttributeCopier { * downstream modifies, because updates to constituents are not modifies to their rows in the aggregation * output table, but rather table updates to be propagated. *

- * This exists in each cycle between - * {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int)} and + * This exists in each cycle between {@link IterativeChunkedAggregationOperator#resetForStep(TableUpdate, int)} and * {@link IterativeChunkedAggregationOperator#propagateUpdates(TableUpdate, RowSet)} *

* If this ever becomes necessary in other operators, it could be moved out to the helper the way modified From 839d21511e66e37378fe7d88073d70180958daf9 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 26 Sep 2022 08:27:47 -0700 Subject: [PATCH 23/25] another round of comments addressed --- .../rowset/impl/BitmapRandomBuilder.java | 96 ++++++++++++++ .../table/impl/by/AggregationContext.java | 6 +- .../by/ChunkedOperatorAggregationHelper.java | 88 +------------ .../table/impl/by/GroupByChunkedOperator.java | 117 +++++++++--------- 4 files changed, 160 insertions(+), 147 deletions(-) create mode 100644 engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java new file mode 100644 index 00000000000..a56fd1e0d87 --- /dev/null +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java @@ -0,0 +1,96 @@ +package io.deephaven.engine.rowset.impl; + +import io.deephaven.engine.rowset.RowSetBuilderRandom; +import io.deephaven.engine.rowset.RowSetBuilderSequential; +import io.deephaven.engine.rowset.RowSetFactory; +import io.deephaven.engine.rowset.WritableRowSet; + +import java.util.Arrays; + +/** + * The output RowSet of an aggregation is fairly special. It is always from zero to the number of output rows, and + * while modifying states we randomly add rows to it, potentially touching the same state many times. The normal + * index random builder does not guarantee those values are de-duplicated and requires O(lg n) operations for each + * insertion and building the RowSet. + *

+ * This version is O(1) for updating a modified slot, then linear in the number of output positions (not the number + * of result values) to build the RowSet. The memory usage is 1 bit per output position, vs. the standard builder is + * 128 bits per used value (though with the possibility of collapsing adjacent ranges when they are modified + * back-to-back). For random access patterns, this version will be more efficient; for friendly patterns the default + * random builder is likely more efficient. + *

+ * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key + * for the builder to the maximum output position without loss of fidelity. + */ +public class BitmapRandomBuilder implements RowSetBuilderRandom { + + /** + * An upper bound on {@code lastUsed}. That is, the highest bit index that may be used in {@code bitset}. + */ + final int maxKey; + + /** + * The lowest set bit index in {@code bitset}. + */ + int firstUsed = Integer.MAX_VALUE; + + /** + * The highest set bit index in {@code bitset}. + */ + int lastUsed = -1; + + /** + * The bitset itself. + */ + long[] bitset; + + public BitmapRandomBuilder(int maxKey) { + this.maxKey = maxKey; + } + + private static int rowKeyToArrayIndex(long rowKey) { + return (int) (rowKey / 64); + } + + @Override + public WritableRowSet build() { + final RowSetBuilderSequential seqBuilder = RowSetFactory.builderSequential(); + for (int ii = firstUsed; ii <= lastUsed; ++ii) { + long word = bitset[ii]; + long rowKey = ii * 64L; + + while (word != 0) { + if ((word & 1) != 0) { + seqBuilder.appendKey(rowKey); + } + rowKey++; + word >>>= 1; + } + } + return seqBuilder.build(); + } + + @Override + public void addKey(final long rowKey) { + if (rowKey >= maxKey) { + return; + } + int index = rowKeyToArrayIndex(rowKey); + if (bitset == null) { + final int maxSize = (maxKey + 63) / 64; + bitset = new long[Math.min(maxSize, (index + 1) * 2)]; + } else if (index >= bitset.length) { + final int maxSize = (maxKey + 63) / 64; + bitset = Arrays.copyOf(bitset, Math.min(maxSize, Math.max(bitset.length * 2, index + 1))); + } + bitset[index] |= 1L << rowKey; + firstUsed = Math.min(index, firstUsed); + lastUsed = Math.max(index, lastUsed); + } + + @Override + public void addRange(final long firstRowKey, final long lastRowKey) { + // This class is used only with aggregation state managers, which never call addRange. + throw new UnsupportedOperationException(); + } +} diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java index 657e1471a0f..bde0c7694b6 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/AggregationContext.java @@ -234,11 +234,11 @@ ModifiedColumnSet[] getInputModifiedColumnSets(QueryTable input) { * initialization. * * @param resultTable The result {@link QueryTable} after initialization - * @param maxDestination The maximum destination slot created during initialization + * @param startingDestinationsCount The number of used destinations at the beginning of this step */ - void propagateInitialStateToOperators(@NotNull final QueryTable resultTable, final int maxDestination) { + void propagateInitialStateToOperators(@NotNull final QueryTable resultTable, final int startingDestinationsCount) { for (final IterativeChunkedAggregationOperator operator : operators) { - operator.propagateInitialState(resultTable, maxDestination); + operator.propagateInitialState(resultTable, startingDestinationsCount); } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index 1aad376e62e..afdf34929b3 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -13,6 +13,7 @@ import io.deephaven.configuration.Configuration; import io.deephaven.datastructures.util.SmartKey; import io.deephaven.engine.rowset.RowSetFactory; +import io.deephaven.engine.rowset.impl.BitmapRandomBuilder; import io.deephaven.engine.table.*; import io.deephaven.engine.rowset.*; import io.deephaven.engine.rowset.RowSequenceFactory; @@ -2398,92 +2399,5 @@ public void addRange(final long firstRowKey, final long lastRowKey) { } } - /** - * The output RowSet of an aggregation is fairly special. It is always from zero to the number of output rows, and - * while modifying states we randomly add rows to it, potentially touching the same state many times. The normal - * index random builder does not guarantee those values are de-duplicated and requires O(lg n) operations for each - * insertion and building the RowSet. - * - * This version is O(1) for updating a modified slot, then linear in the number of output positions (not the number - * of result values) to build the RowSet. The memory usage is 1 bit per output position, vs. the standard builder is - * 128 bits per used value (though with the possibility of collapsing adjacent ranges when they are modified - * back-to-back). For random access patterns, this version will be more efficient; for friendly patterns the default - * random builder is likely more efficient. - * - * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key - * for the builder to the maximum output position without loss of fidelity. - */ - public static class BitmapRandomBuilder implements RowSetBuilderRandom { - - /** - * An upper bound on {@code lastUsed}. That is, the highest bit index that may be used in {@code bitset}. - */ - final int maxKey; - - /** - * The lowest set bit index in {@code bitset}. - */ - int firstUsed = Integer.MAX_VALUE; - - /** - * The highest set bit index in {@code bitset}. - */ - int lastUsed = -1; - - /** - * The bitset itself. - */ - long[] bitset; - - public BitmapRandomBuilder(int maxKey) { - this.maxKey = maxKey; - } - - private static int rowKeyToArrayIndex(long rowKey) { - return (int) (rowKey / 64); - } - - @Override - public WritableRowSet build() { - final RowSetBuilderSequential seqBuilder = RowSetFactory.builderSequential(); - for (int ii = firstUsed; ii <= lastUsed; ++ii) { - long word = bitset[ii]; - long rowKey = ii * 64L; - - while (word != 0) { - if ((word & 1) != 0) { - seqBuilder.appendKey(rowKey); - } - rowKey++; - word >>>= 1; - } - } - return seqBuilder.build(); - } - - @Override - public void addKey(final long rowKey) { - if (rowKey >= maxKey) { - return; - } - int index = rowKeyToArrayIndex(rowKey); - if (bitset == null) { - final int maxSize = (maxKey + 63) / 64; - bitset = new long[Math.min(maxSize, (index + 1) * 2)]; - } else if (index >= bitset.length) { - final int maxSize = (maxKey + 63) / 64; - bitset = Arrays.copyOf(bitset, Math.min(maxSize, Math.max(bitset.length * 2, index + 1))); - } - bitset[index] |= 1L << rowKey; - firstUsed = Math.min(index, firstUsed); - lastUsed = Math.max(index, lastUsed); - } - - @Override - public void addRange(final long firstRowKey, final long lastRowKey) { - // This class is used only with aggregation state managers, which never call addRange. - throw new UnsupportedOperationException(); - } - } } diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 497599ea4b3..16c41ab9123 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -9,6 +9,7 @@ import io.deephaven.chunk.attributes.Values; import io.deephaven.datastructures.util.CollectionUtil; import io.deephaven.engine.rowset.RowSetFactory; +import io.deephaven.engine.rowset.impl.BitmapRandomBuilder; import io.deephaven.engine.table.*; import io.deephaven.engine.rowset.*; import io.deephaven.engine.liveness.LivenessReferent; @@ -48,7 +49,7 @@ public final class GroupByChunkedOperator private final Map> resultColumns; private final ModifiedColumnSet resultInputsModifiedColumnSet; - private ChunkedOperatorAggregationHelper.BitmapRandomBuilder stepDestinationsModified; + private RowSetBuilderRandom stepDestinationsModified; private boolean stepValuesModified; private boolean someKeyHasAddsOrRemoves; @@ -435,7 +436,7 @@ public void resetForStep(@NotNull final TableUpdate upstream, final int starting && upstream.modifiedColumnSet().containsAny(resultInputsModifiedColumnSet); someKeyHasAddsOrRemoves = false; someKeyHasModifies = false; - stepDestinationsModified = new ChunkedOperatorAggregationHelper.BitmapRandomBuilder(startingDestinationsCount); + stepDestinationsModified = new BitmapRandomBuilder(startingDestinationsCount); } @Override @@ -488,63 +489,65 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin // add the new destinations so a rowset will get created if it doesn't exist stepDestinations.insert(newDestinations); + if (stepDestinations.isEmpty()) { + return; + } + // use the builders to modify the rowsets - if (stepDestinations.isNonempty()) { - try (final ResettableWritableObjectChunk rowSetResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator destinationsIterator = - stepDestinations.getRowSequenceIterator()) { - - // noinspection unchecked - final WritableObjectChunk rowSetBackingChunk = - rowSetResettableChunk.asWritableObjectChunk(); - // noinspection unchecked - final WritableObjectChunk addedBuildersBackingChunk = - addedBuildersResettableChunk.asWritableObjectChunk(); - // noinspection unchecked - final WritableObjectChunk removedBuildersBackingChunk = - removedBuildersResettableChunk.asWritableObjectChunk(); - - while (destinationsIterator.hasMore()) { - final long firstSliceDestination = destinationsIterator.peekNextKey(); - final long firstBackingChunkDestination = - rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); - addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, - firstSliceDestination); - removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, - firstSliceDestination); - - final long lastBackingChunkDestination = - firstBackingChunkDestination + rowSetBackingChunk.size() - 1; - final RowSequence initialDestinationsSlice = - destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); - - initialDestinationsSlice.forAllRowKeys((final long destination) -> { - final int backingChunkOffset = - Math.toIntExact(destination - firstBackingChunkDestination); - final WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); - if (workingRowSet == null) { - // use the addRowSet as the new rowset - final WritableRowSet addRowSet = nullToEmpty( - extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); - rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); - } else { - try (final WritableRowSet addRowSet = - nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, - backingChunkOffset)); - final WritableRowSet removeRowSet = - nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, - backingChunkOffset))) { - workingRowSet.remove(removeRowSet); - workingRowSet.insert(addRowSet); - } + try (final ResettableWritableObjectChunk rowSetResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + stepDestinations.getRowSequenceIterator()) { + + // noinspection unchecked + final WritableObjectChunk rowSetBackingChunk = + rowSetResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk addedBuildersBackingChunk = + addedBuildersResettableChunk.asWritableObjectChunk(); + // noinspection unchecked + final WritableObjectChunk removedBuildersBackingChunk = + removedBuildersResettableChunk.asWritableObjectChunk(); + + while (destinationsIterator.hasMore()) { + final long firstSliceDestination = destinationsIterator.peekNextKey(); + final long firstBackingChunkDestination = + rowSets.resetWritableChunkToBackingStore(rowSetResettableChunk, firstSliceDestination); + addedBuilders.resetWritableChunkToBackingStore(addedBuildersResettableChunk, + firstSliceDestination); + removedBuilders.resetWritableChunkToBackingStore(removedBuildersResettableChunk, + firstSliceDestination); + + final long lastBackingChunkDestination = + firstBackingChunkDestination + rowSetBackingChunk.size() - 1; + final RowSequence initialDestinationsSlice = + destinationsIterator.getNextRowSequenceThrough(lastBackingChunkDestination); + + initialDestinationsSlice.forAllRowKeys((final long destination) -> { + final int backingChunkOffset = + Math.toIntExact(destination - firstBackingChunkDestination); + final WritableRowSet workingRowSet = rowSetBackingChunk.get(backingChunkOffset); + if (workingRowSet == null) { + // use the addRowSet as the new rowset + final WritableRowSet addRowSet = nullToEmpty( + extractAndClearBuilderRandom(addedBuildersBackingChunk, backingChunkOffset)); + rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); + } else { + try (final WritableRowSet addRowSet = + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, + backingChunkOffset)); + final WritableRowSet removeRowSet = + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, + backingChunkOffset))) { + workingRowSet.remove(removeRowSet); + workingRowSet.insert(addRowSet); } - }); - } + } + }); } } stepDestinationsModified = null; From 813d34f139c76b821f979499bbb938aaf8ef5f30 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 26 Sep 2022 09:04:34 -0700 Subject: [PATCH 24/25] more spotless --- .../rowset/impl/BitmapRandomBuilder.java | 22 ++++++++--------- .../table/impl/by/GroupByChunkedOperator.java | 24 +++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java index a56fd1e0d87..f563b3a433c 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java +++ b/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java @@ -8,19 +8,19 @@ import java.util.Arrays; /** - * The output RowSet of an aggregation is fairly special. It is always from zero to the number of output rows, and - * while modifying states we randomly add rows to it, potentially touching the same state many times. The normal - * index random builder does not guarantee those values are de-duplicated and requires O(lg n) operations for each - * insertion and building the RowSet. + * The output RowSet of an aggregation is fairly special. It is always from zero to the number of output rows, and while + * modifying states we randomly add rows to it, potentially touching the same state many times. The normal index random + * builder does not guarantee those values are de-duplicated and requires O(lg n) operations for each insertion and + * building the RowSet. *

- * This version is O(1) for updating a modified slot, then linear in the number of output positions (not the number - * of result values) to build the RowSet. The memory usage is 1 bit per output position, vs. the standard builder is - * 128 bits per used value (though with the possibility of collapsing adjacent ranges when they are modified - * back-to-back). For random access patterns, this version will be more efficient; for friendly patterns the default - * random builder is likely more efficient. + * This version is O(1) for updating a modified slot, then linear in the number of output positions (not the number of + * result values) to build the RowSet. The memory usage is 1 bit per output position, vs. the standard builder is 128 + * bits per used value (though with the possibility of collapsing adjacent ranges when they are modified back-to-back). + * For random access patterns, this version will be more efficient; for friendly patterns the default random builder is + * likely more efficient. *

- * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key - * for the builder to the maximum output position without loss of fidelity. + * We also know that we will only modify the rows that existed when we start, so that we can clamp the maximum key for + * the builder to the maximum output position without loss of fidelity. */ public class BitmapRandomBuilder implements RowSetBuilderRandom { diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 16c41ab9123..340c5ad77bd 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -495,13 +495,13 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin // use the builders to modify the rowsets try (final ResettableWritableObjectChunk rowSetResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk addedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final ResettableWritableObjectChunk removedBuildersResettableChunk = - ResettableWritableObjectChunk.makeResettableChunk(); - final RowSequence.Iterator destinationsIterator = - stepDestinations.getRowSequenceIterator()) { + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk addedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final ResettableWritableObjectChunk removedBuildersResettableChunk = + ResettableWritableObjectChunk.makeResettableChunk(); + final RowSequence.Iterator destinationsIterator = + stepDestinations.getRowSequenceIterator()) { // noinspection unchecked final WritableObjectChunk rowSetBackingChunk = @@ -538,11 +538,11 @@ public void propagateUpdates(@NotNull final TableUpdate downstream, @NotNull fin rowSetBackingChunk.set(backingChunkOffset, live ? addRowSet.toTracking() : addRowSet); } else { try (final WritableRowSet addRowSet = - nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, - backingChunkOffset)); - final WritableRowSet removeRowSet = - nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, - backingChunkOffset))) { + nullToEmpty(extractAndClearBuilderRandom(addedBuildersBackingChunk, + backingChunkOffset)); + final WritableRowSet removeRowSet = + nullToEmpty(extractAndClearBuilderRandom(removedBuildersBackingChunk, + backingChunkOffset))) { workingRowSet.remove(removeRowSet); workingRowSet.insert(addRowSet); } From 7c3fff68e02be8311df65191df711a45d23c9535 Mon Sep 17 00:00:00 2001 From: Larry Booker Date: Mon, 26 Sep 2022 09:34:58 -0700 Subject: [PATCH 25/25] Moved BitmapRandomBuilder to a better home --- .../io/deephaven/engine/table/impl/by}/BitmapRandomBuilder.java | 2 +- .../engine/table/impl/by/ChunkedOperatorAggregationHelper.java | 1 - .../deephaven/engine/table/impl/by/GroupByChunkedOperator.java | 1 - 3 files changed, 1 insertion(+), 3 deletions(-) rename engine/{rowset/src/main/java/io/deephaven/engine/rowset/impl => table/src/main/java/io/deephaven/engine/table/impl/by}/BitmapRandomBuilder.java (98%) diff --git a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BitmapRandomBuilder.java similarity index 98% rename from engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java rename to engine/table/src/main/java/io/deephaven/engine/table/impl/by/BitmapRandomBuilder.java index f563b3a433c..2ded5be0150 100644 --- a/engine/rowset/src/main/java/io/deephaven/engine/rowset/impl/BitmapRandomBuilder.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/BitmapRandomBuilder.java @@ -1,4 +1,4 @@ -package io.deephaven.engine.rowset.impl; +package io.deephaven.engine.table.impl.by; import io.deephaven.engine.rowset.RowSetBuilderRandom; import io.deephaven.engine.rowset.RowSetBuilderSequential; diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java index afdf34929b3..2bca15a0c77 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/ChunkedOperatorAggregationHelper.java @@ -13,7 +13,6 @@ import io.deephaven.configuration.Configuration; import io.deephaven.datastructures.util.SmartKey; import io.deephaven.engine.rowset.RowSetFactory; -import io.deephaven.engine.rowset.impl.BitmapRandomBuilder; import io.deephaven.engine.table.*; import io.deephaven.engine.rowset.*; import io.deephaven.engine.rowset.RowSequenceFactory; diff --git a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java index 340c5ad77bd..1a860953f3a 100644 --- a/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java +++ b/engine/table/src/main/java/io/deephaven/engine/table/impl/by/GroupByChunkedOperator.java @@ -9,7 +9,6 @@ import io.deephaven.chunk.attributes.Values; import io.deephaven.datastructures.util.CollectionUtil; import io.deephaven.engine.rowset.RowSetFactory; -import io.deephaven.engine.rowset.impl.BitmapRandomBuilder; import io.deephaven.engine.table.*; import io.deephaven.engine.rowset.*; import io.deephaven.engine.liveness.LivenessReferent;