Skip to content

Commit

Permalink
Remove order affecting operations under certain conditions
Browse files Browse the repository at this point in the history
Conditions are described in #33
  • Loading branch information
dekmm committed Aug 10, 2020
1 parent 9e61359 commit 6dd1fea
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@

package com.speedment.jpastreamer.interopoptimizer.standard.internal;

import com.speedment.jpastreamer.interopoptimizer.IntermediateOperationOptimizer;
import com.speedment.jpastreamer.interopoptimizer.IntermediateOperationOptimizerFactory;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.RemoveOrderAffectingOperations;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashDistinct;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashFilter;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashLimit;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashSkip;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashSorted;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationFactory;
import com.speedment.jpastreamer.interopoptimizer.IntermediateOperationOptimizer;
import com.speedment.jpastreamer.interopoptimizer.IntermediateOperationOptimizerFactory;
import com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy.SquashSkip;
import com.speedment.jpastreamer.rootfactory.RootFactory;

import java.util.ArrayList;
Expand All @@ -39,6 +40,7 @@ public InternalIntermediateOperationOptimizerFactory() {
final IntermediateOperationFactory intermediateOperationFactory = RootFactory
.getOrThrow(IntermediateOperationFactory.class, ServiceLoader::load);

intermediateOperationOptimizers.add(new RemoveOrderAffectingOperations());
intermediateOperationOptimizers.add(new SquashSkip(intermediateOperationFactory));
intermediateOperationOptimizers.add(new SquashLimit(intermediateOperationFactory));
intermediateOperationOptimizers.add(new SquashFilter<>(intermediateOperationFactory));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2006-2020, Speedment, Inc. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); You may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

package com.speedment.jpastreamer.interopoptimizer.standard.internal.strategy;

import static com.speedment.jpastreamer.pipeline.intermediate.Statement.MODIFIES_ORDER;
import static com.speedment.jpastreamer.pipeline.intermediate.Statement.MODIFIES_SORTED;
import static com.speedment.jpastreamer.pipeline.intermediate.Verb.MODIFIES;
import static com.speedment.jpastreamer.pipeline.terminal.OrderPreservation.NOT_REQUIRED;
import static com.speedment.jpastreamer.pipeline.terminal.OrderPreservation.NOT_REQUIRED_IF_PARALLEL;

import com.speedment.jpastreamer.interopoptimizer.IntermediateOperationOptimizer;
import com.speedment.jpastreamer.pipeline.Pipeline;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperation;
import com.speedment.jpastreamer.pipeline.intermediate.IntermediateOperationType;
import com.speedment.jpastreamer.pipeline.terminal.OrderPreservation;

import java.util.LinkedList;

public final class RemoveOrderAffectingOperations implements IntermediateOperationOptimizer {

@Override
public <T> Pipeline<T> optimize(Pipeline<T> pipeline) {
final OrderPreservation termOpOrderPreservation = pipeline.terminatingOperation().type().orderPreservation();

if (pipeline.isUnordered() || termOpOrderPreservation == NOT_REQUIRED ||
(pipeline.isParallel() && termOpOrderPreservation == NOT_REQUIRED_IF_PARALLEL)) {

final LinkedList<IntermediateOperation<?, ?>> intermediateOperations = pipeline.intermediateOperations();

for (int i = intermediateOperations.size() - 1; i >= 0; i--) {
final IntermediateOperationType intermediateOperationType = intermediateOperations.get(i).type();

final boolean canBeRemoved = intermediateOperationType.statements().stream()
.filter(statement -> statement.verb() == MODIFIES)
.allMatch(statement -> statement == MODIFIES_ORDER || statement == MODIFIES_SORTED);

if (!canBeRemoved) {
break;
}

intermediateOperations.remove(i);
}
}

return pipeline;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,24 @@ public <T> Pipeline<T> optimize(final Pipeline<T> pipeline) {
final IntermediateOperation<?, ?> intermediateOperation = intermediateOperations.get(i);

if (intermediateOperation.type() == operationType()) {
if (intermediateOperation.arguments().length == 0) {
if (result != checkValue()) {
final IntermediateOperation<?, ?> newOperation = operationProvider()
.apply(result);
intermediateOperations.add(i + 1, newOperation);

result = resetValue();
}
continue;
}

if (valueClass().isAssignableFrom(intermediateOperation.arguments()[0].getClass())) {
S value = (S) intermediateOperation.arguments()[0];
result = squash().apply(value, result);

intermediateOperations.remove(i);
}

continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,17 @@ public <T> void modifyCriteria(

criteria.getQuery().orderBy(orders);

mergingTracker.markAsMerged(operationType);
/*
* If a Stream::sorted sequence contains a operation without a specified comparator
* we cannot squash that sequence into a single operation. Because of this, we should
* only mark the operation as merged if it's the last one in the sequence.
* */
operationReference.next().ifPresent(op -> {
if (op.get().type() != SORTED) {
mergingTracker.markAsMerged(operationType);
}
});

mergingTracker.markForRemoval(operationReference.index());
} else {
final EntityType<T> entityType = criteria.getRoot().getModel();
Expand All @@ -93,7 +103,12 @@ public <T> void modifyCriteria(

criteria.getQuery().orderBy(order);

mergingTracker.markAsMerged(operationType);
operationReference.next().ifPresent(op -> {
if (op.get().type() != SORTED) {
mergingTracker.markAsMerged(operationType);
}
});

mergingTracker.markForRemoval(operationReference.index());
});
}
Expand Down

0 comments on commit 6dd1fea

Please sign in to comment.