All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.optimizer.traversals.PlanFinalizer Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.flink.optimizer.traversals;

import org.apache.flink.api.common.Plan;
import org.apache.flink.optimizer.CompilerException;
import org.apache.flink.optimizer.Optimizer;
import org.apache.flink.optimizer.dag.TempMode;
import org.apache.flink.optimizer.plan.BinaryUnionPlanNode;
import org.apache.flink.optimizer.plan.BulkIterationPlanNode;
import org.apache.flink.optimizer.plan.BulkPartialSolutionPlanNode;
import org.apache.flink.optimizer.plan.Channel;
import org.apache.flink.optimizer.plan.IterationPlanNode;
import org.apache.flink.optimizer.plan.OptimizedPlan;
import org.apache.flink.optimizer.plan.PlanNode;
import org.apache.flink.optimizer.plan.SinkPlanNode;
import org.apache.flink.optimizer.plan.SolutionSetPlanNode;
import org.apache.flink.optimizer.plan.SourcePlanNode;
import org.apache.flink.optimizer.plan.WorksetIterationPlanNode;
import org.apache.flink.optimizer.plan.WorksetPlanNode;
import org.apache.flink.runtime.operators.DriverStrategy;
import org.apache.flink.util.Visitor;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * This visitor traverses the selected execution plan and finalizes it:
 *
 * 
    *
  • The graph of nodes is double-linked (links from child to parent are inserted). *
  • If unions join static and dynamic paths, the cache is marked as a memory consumer. *
  • Relative memory fractions are assigned to all nodes. *
  • All nodes are collected into a set. *
*/ public class PlanFinalizer implements Visitor { private final Set allNodes; // a set of all nodes in the optimizer plan private final List sources; // all data source nodes in the optimizer plan private final List sinks; // all data sink nodes in the optimizer plan private final Deque stackOfIterationNodes; private int memoryConsumerWeights; // a counter of all memory consumers /** Creates a new plan finalizer. */ public PlanFinalizer() { this.allNodes = new HashSet(); this.sources = new ArrayList(); this.sinks = new ArrayList(); this.stackOfIterationNodes = new ArrayDeque(); } public OptimizedPlan createFinalPlan( List sinks, String jobName, Plan originalPlan) { this.memoryConsumerWeights = 0; // traverse the graph for (SinkPlanNode node : sinks) { node.accept(this); } // assign the memory to each node if (this.memoryConsumerWeights > 0) { for (PlanNode node : this.allNodes) { // assign memory to the driver strategy of the node final int consumerWeight = node.getMemoryConsumerWeight(); if (consumerWeight > 0) { final double relativeMem = (double) consumerWeight / this.memoryConsumerWeights; node.setRelativeMemoryPerSubtask(relativeMem); if (Optimizer.LOG.isDebugEnabled()) { Optimizer.LOG.debug( "Assigned " + relativeMem + " of total memory to each subtask of " + node.getProgramOperator().getName() + "."); } } // assign memory to the local and global strategies of the channels for (Channel c : node.getInputs()) { if (c.getLocalStrategy().dams()) { final double relativeMem = 1.0 / this.memoryConsumerWeights; c.setRelativeMemoryLocalStrategy(relativeMem); if (Optimizer.LOG.isDebugEnabled()) { Optimizer.LOG.debug( "Assigned " + relativeMem + " of total memory to each local strategy " + "instance of " + c + "."); } } if (c.getTempMode() != TempMode.NONE) { final double relativeMem = 1.0 / this.memoryConsumerWeights; c.setRelativeTempMemory(relativeMem); if (Optimizer.LOG.isDebugEnabled()) { Optimizer.LOG.debug( "Assigned " + relativeMem + " of total memory to each instance of the temp " + "table for " + c + "."); } } } } } return new OptimizedPlan(this.sources, this.sinks, this.allNodes, jobName, originalPlan); } @Override public boolean preVisit(PlanNode visitable) { // if we come here again, prevent a further descend if (!this.allNodes.add(visitable)) { return false; } if (visitable instanceof SinkPlanNode) { this.sinks.add((SinkPlanNode) visitable); } else if (visitable instanceof SourcePlanNode) { this.sources.add((SourcePlanNode) visitable); } else if (visitable instanceof BinaryUnionPlanNode) { BinaryUnionPlanNode unionNode = (BinaryUnionPlanNode) visitable; if (unionNode.unionsStaticAndDynamicPath()) { unionNode.setDriverStrategy(DriverStrategy.UNION_WITH_CACHED); } } else if (visitable instanceof BulkPartialSolutionPlanNode) { // tell the partial solution about the iteration node that contains it final BulkPartialSolutionPlanNode pspn = (BulkPartialSolutionPlanNode) visitable; final IterationPlanNode iteration = this.stackOfIterationNodes.peekLast(); // sanity check! if (!(iteration instanceof BulkIterationPlanNode)) { throw new CompilerException( "Bug: Error finalizing the plan. " + "Cannot associate the node for a partial solutions with its containing iteration."); } pspn.setContainingIterationNode((BulkIterationPlanNode) iteration); } else if (visitable instanceof WorksetPlanNode) { // tell the partial solution about the iteration node that contains it final WorksetPlanNode wspn = (WorksetPlanNode) visitable; final IterationPlanNode iteration = this.stackOfIterationNodes.peekLast(); // sanity check! if (!(iteration instanceof WorksetIterationPlanNode)) { throw new CompilerException( "Bug: Error finalizing the plan. " + "Cannot associate the node for a partial solutions with its containing iteration."); } wspn.setContainingIterationNode((WorksetIterationPlanNode) iteration); } else if (visitable instanceof SolutionSetPlanNode) { // tell the partial solution about the iteration node that contains it final SolutionSetPlanNode sspn = (SolutionSetPlanNode) visitable; final IterationPlanNode iteration = this.stackOfIterationNodes.peekLast(); // sanity check! if (!(iteration instanceof WorksetIterationPlanNode)) { throw new CompilerException( "Bug: Error finalizing the plan. " + "Cannot associate the node for a partial solutions with its containing iteration."); } sspn.setContainingIterationNode((WorksetIterationPlanNode) iteration); } // double-connect the connections. previously, only parents knew their children, because // one child candidate could have been referenced by multiple parents. for (Channel conn : visitable.getInputs()) { conn.setTarget(visitable); conn.getSource().addOutgoingChannel(conn); } for (Channel c : visitable.getBroadcastInputs()) { c.setTarget(visitable); c.getSource().addOutgoingChannel(c); } // count the memory consumption this.memoryConsumerWeights += visitable.getMemoryConsumerWeight(); for (Channel c : visitable.getInputs()) { if (c.getLocalStrategy().dams()) { this.memoryConsumerWeights++; } if (c.getTempMode() != TempMode.NONE) { this.memoryConsumerWeights++; } } for (Channel c : visitable.getBroadcastInputs()) { if (c.getLocalStrategy().dams()) { this.memoryConsumerWeights++; } if (c.getTempMode() != TempMode.NONE) { this.memoryConsumerWeights++; } } // pass the visitor to the iteration's step function if (visitable instanceof IterationPlanNode) { // push the iteration node onto the stack final IterationPlanNode iterNode = (IterationPlanNode) visitable; this.stackOfIterationNodes.addLast(iterNode); // recurse ((IterationPlanNode) visitable).acceptForStepFunction(this); // pop the iteration node from the stack this.stackOfIterationNodes.removeLast(); } return true; } @Override public void postVisit(PlanNode visitable) {} }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy