/** * Create an instance that pushes {@link CardinalityEstimate}s through a data flow plan starting at the given * {@code inputSlots} and {@code sourceOperators}, thereby putting {@link CardinalityEstimate}s into the * {@code cache}. * * @param inputSlots open {@link InputSlot}s that will be initially activated * @param sourceOperators {@link Operator} that will be initially activated * @param configuration provides utilties for the estimation */ public static CardinalityEstimationTraversal createPushTraversal(Collection<InputSlot<?>> inputSlots, Collection<Operator> sourceOperators, Configuration configuration) { return createPushTraversal(inputSlots, Collections.emptySet(), sourceOperators, configuration); }
/** * Traverse and update {@link CardinalityEstimate}s. * * @param optimizationContext provides input {@link CardinalityEstimate}s and stores all produces * {@link CardinalityEstimate}s alongside the push traversal * @param configuration provides the applicable {@link Configuration} * @return whether any {@link CardinalityEstimate}s have been updated */ public boolean traverse(OptimizationContext optimizationContext, Configuration configuration) { boolean isUpdated = false; try { final Queue<Activator> activators = this.initializeActivatorQueue(); do { assert !activators.isEmpty() : String.format("No source activators. (input activations: %s)", this.inputActivations); final Activator activator = activators.poll(); isUpdated |= activator.process(optimizationContext, configuration, activators); } while (!activators.isEmpty()); } finally { this.reset(); } return isUpdated; }
private void resetDownstream(Activator activator) { this.resetAll(Stream.of(activator)); }
/** * Trigger the {@link CardinalityEstimationTraversal} for the given {@code traversal}. */ private void pushThroughPath(Tuple<OperatorAlternative.Alternative, CardinalityEstimationTraversal> traversal, Configuration configuration, OptimizationContext optimizationCtx) { // Perform the push. traversal.field1.traverse(optimizationCtx, configuration); }
this.result = new CardinalityEstimationTraversal(requiredActivations, sourceActivators);
/** * Traverse the {@link RheemPlan}, thereby updating {@link CardinalityEstimate}s. * * @return whether any {@link CardinalityEstimate}s have been updated */ public boolean pushCardinalities() { boolean isUpdated = this.getPlanTraversal().traverse(this.optimizationContext, this.configuration); this.optimizationContext.clearMarks(); return isUpdated; }
public CardinalityEstimationTraversal getPlanTraversal() { if (this.planTraversal == null) { this.planTraversal = CardinalityEstimationTraversal.createPushTraversal( Collections.emptyList(), this.rheemPlan.collectReachableTopLevelSources(), this.configuration ); } return this.planTraversal; }
/** * Traverse the {@link RheemPlan}, thereby updating {@link CardinalityEstimate}s. Also update conversion * {@link Operator} cardinalities as provided by the {@link PlanImplementation}. * * @param planImplementation that has conversion {@link Operator}s * @return whether any {@link CardinalityEstimate}s have been updated */ public boolean pushCardinalities(PlanImplementation planImplementation) { boolean isUpdated = this.getPlanTraversal().traverse(this.optimizationContext, this.configuration); planImplementation.getLoopImplementations().keySet().forEach( loop -> this.optimizationContext.getNestedLoopContext(loop).getAggregateContext().updateOperatorContexts() ); this.updateConversionOperatorCardinalities(planImplementation, this.optimizationContext, 0); this.optimizationContext.clearMarks(); return isUpdated; }
/** * Resets this instance, so that it perform a new traversal. */ private void reset() { this.resetAll(Stream.concat( this.inputActivations.stream().map(Activation::getTargetActivator), this.sourceActivators.stream() )); }
public OperatorAlternativeCardinalityPusher(final OperatorAlternative operatorAlternative, final Configuration configuration ) { super(operatorAlternative); this.alternativeTraversals = operatorAlternative.getAlternatives().stream() .map(alternative -> { final CardinalityEstimationTraversal traversal = CardinalityEstimationTraversal.createPushTraversal(alternative, configuration); return new Tuple<>(alternative, traversal); }) .collect(Collectors.toList()); }
@Override protected void doPush(OptimizationContext.OperatorContext opCtx, Configuration configuration) { // Kick the traversal off. this.traversal.traverse(opCtx.getOptimizationContext(), configuration); // Pull the cardinalities for the OutputSlots. Subplan subplan = (Subplan) opCtx.getOperator(); for (int outputIndex = 0; outputIndex < subplan.getNumOutputs(); outputIndex++) { final OutputSlot<?> innerOutput = subplan.traceOutput(subplan.getOutput(outputIndex)); if (innerOutput != null) { final OptimizationContext.OperatorContext innerOperatorCtx = opCtx.getOptimizationContext().getOperatorContext(innerOutput.getOwner()); final CardinalityEstimate cardinality = innerOperatorCtx.getOutputCardinality(innerOutput.getIndex()); opCtx.setOutputCardinality(outputIndex, cardinality); } } }
/** * Create an instance that pushes {@link CardinalityEstimate}s through a data flow plan starting at the given * {@code inputSlots} and {@code sourceOperators}, thereby putting {@link CardinalityEstimate}s into the * {@code cache}. * * @param operatorContainer that should be traversed * @param configuration provides utilities for the estimation */ public static CardinalityEstimationTraversal createPushTraversal(OperatorContainer operatorContainer, Configuration configuration) { if (operatorContainer.isSource()) { return createPushTraversal( Collections.emptyList(), Collections.singleton(operatorContainer.getSource()), configuration ); } else { return createPushTraversal( operatorContainer.getMappedInputs(), Collections.emptyList(), configuration ); } }
this.bodyTraversal.traverse(iterationCtx, configuration); for (OutputSlot<?> bodyOutputSlot : this.bodyOutputSlots) { final Operator bodyOperator = bodyOutputSlot.getOwner();
/** * Create an instance for the given {@link Subplan}. * * @return the instance if it could be created */ public static CardinalityPusher createFor(OperatorContainer container, Configuration configuration) { final CompositeOperator compositeOperator = container.toOperator(); final InputSlot<?>[] outerInputs = compositeOperator.getAllInputs(); final List<InputSlot<?>> innerInputs = Arrays.stream(outerInputs) .flatMap(inputSlot -> container.followInput(inputSlot).stream()) .collect(Collectors.toList()); final Collection<Operator> sourceOperators = compositeOperator.isSource() ? Collections.singleton(container.getSource()) : Collections.emptySet(); final CardinalityEstimationTraversal traversal = CardinalityEstimationTraversal.createPushTraversal( innerInputs, sourceOperators, configuration); return new SubplanCardinalityPusher(traversal, compositeOperator); }
public LoopSubplanCardinalityPusher(LoopSubplan loopSubplan, Configuration configuration) { super(loopSubplan); // Create the CardinalityPusher for the loop head. final LoopHeadOperator loopHead = loopSubplan.getLoopHead(); this.loopHeadInitializationPusher = loopHead.getInitializationPusher(configuration); this.loopHeadIterationPusher = loopHead.getCardinalityPusher(configuration); this.loopHeadFinalizationPusher = loopHead.getFinalizationPusher(configuration); // Create the CardinalityTraversal for the loop body. Set<InputSlot<?>> bodyInputSlots = Arrays.stream(loopSubplan.getAllInputs()) .flatMap(outerInput -> loopSubplan.followInput(outerInput).stream()) .collect(Collectors.toSet()); for (InputSlot<?> inputSlot : loopHead.getLoopInitializationInputs()) { bodyInputSlots.remove(inputSlot); } for (OutputSlot<?> outputSlot : loopHead.getLoopBodyOutputs()) { for (InputSlot<?> inputSlot : outputSlot.getOccupiedSlots()) { bodyInputSlots.add(inputSlot); } } this.bodyOutputSlots = loopHead.getLoopBodyInputs().stream() .map(InputSlot::getOccupant) .filter(Objects::nonNull) .collect(Collectors.toSet()); this.bodyTraversal = CardinalityEstimationTraversal.createPushTraversal( bodyInputSlots, loopHead.getLoopBodyInputs(), Collections.emptyList(), configuration); }