io.ray.streaming.jobgraph.JobGraphOptimizer Maven / Gradle / Ivy
package io.ray.streaming.jobgraph;
import io.ray.streaming.api.Language;
import io.ray.streaming.api.partition.Partition;
import io.ray.streaming.api.partition.impl.ForwardPartition;
import io.ray.streaming.api.partition.impl.RoundRobinPartition;
import io.ray.streaming.operator.ChainStrategy;
import io.ray.streaming.operator.StreamOperator;
import io.ray.streaming.operator.chain.ChainedOperator;
import io.ray.streaming.python.PythonOperator;
import io.ray.streaming.python.PythonOperator.ChainedPythonOperator;
import io.ray.streaming.python.PythonPartition;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
/**
* Optimize job graph by chaining some operators so that some operators can be run in the same
* thread.
*/
public class JobGraphOptimizer {
private final JobGraph jobGraph;
private Set visited = new HashSet<>();
// vertex id -> vertex
private Map vertexMap;
private Map> outputEdgesMap;
// tail vertex id -> mergedVertex
private Map>> mergedVertexMap;
public JobGraphOptimizer(JobGraph jobGraph) {
this.jobGraph = jobGraph;
vertexMap =
jobGraph.getJobVertices().stream()
.collect(Collectors.toMap(JobVertex::getVertexId, Function.identity()));
outputEdgesMap =
vertexMap.keySet().stream()
.collect(
Collectors.toMap(
id -> vertexMap.get(id),
id -> new HashSet<>(jobGraph.getVertexOutputEdges(id))));
mergedVertexMap = new HashMap<>();
}
public JobGraph optimize() {
// Deep-first traverse nodes from source to sink to merge vertices that can be chained
// together.
jobGraph
.getSourceVertices()
.forEach(
vertex -> {
List verticesToMerge = new ArrayList<>();
verticesToMerge.add(vertex);
mergeVerticesRecursively(vertex, verticesToMerge);
});
List vertices =
mergedVertexMap.values().stream().map(Pair::getLeft).collect(Collectors.toList());
return new JobGraph(jobGraph.getJobName(), jobGraph.getJobConfig(), vertices, createEdges());
}
private void mergeVerticesRecursively(JobVertex vertex, List verticesToMerge) {
if (!visited.contains(vertex)) {
visited.add(vertex);
Set outputEdges = outputEdgesMap.get(vertex);
if (outputEdges.isEmpty()) {
mergeAndAddVertex(verticesToMerge);
} else {
outputEdges.forEach(
edge -> {
JobVertex succeedingVertex = vertexMap.get(edge.getTargetVertexId());
if (canBeChained(vertex, succeedingVertex, edge)) {
verticesToMerge.add(succeedingVertex);
mergeVerticesRecursively(succeedingVertex, verticesToMerge);
} else {
mergeAndAddVertex(verticesToMerge);
List newMergedVertices = new ArrayList<>();
newMergedVertices.add(succeedingVertex);
mergeVerticesRecursively(succeedingVertex, newMergedVertices);
}
});
}
}
}
private void mergeAndAddVertex(List verticesToMerge) {
JobVertex mergedVertex;
JobVertex headVertex = verticesToMerge.get(0);
Language language = headVertex.getLanguage();
if (verticesToMerge.size() == 1) {
// no chain
mergedVertex = headVertex;
} else {
List operators =
verticesToMerge.stream()
.map(v -> vertexMap.get(v.getVertexId()).getStreamOperator())
.collect(Collectors.toList());
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy