Skip to content
81 changes: 18 additions & 63 deletions core/src/main/scala/org/apache/spark/MapOutputTracker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ private[spark] abstract class MapOutputTracker(conf: SparkConf) extends Logging
// For testing
def getMapSizesByExecutorId(shuffleId: Int, reduceId: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
getMapSizesByExecutorId(shuffleId, reduceId, reduceId + 1)
getMapSizesByExecutorId(shuffleId, 0, Int.MaxValue, reduceId, reduceId + 1)
}

/**
Expand All @@ -335,28 +335,12 @@ private[spark] abstract class MapOutputTracker(conf: SparkConf) extends Logging
* tuples describing the shuffle blocks that are stored at that block manager.
*/
def getMapSizesByExecutorId(
Comment thread
cloud-fan marked this conversation as resolved.
shuffleId: Int,
startPartition: Int,
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])]

/**
* Called from executors to get the server URIs and output sizes for each shuffle block that
* needs to be read from a given range of map output partitions (startPartition is included but
* endPartition is excluded from the range) and is produced by
* a range of mappers (startMapIndex, endMapIndex, startMapIndex is included and
* the endMapIndex is excluded).
Comment thread
Ngone51 marked this conversation as resolved.
*
* @return A sequence of 2-item tuples, where the first item in the tuple is a BlockManagerId,
* and the second item is a sequence of (shuffle block id, shuffle block size, map index)
* tuples describing the shuffle blocks that are stored at that block manager.
*/
def getMapSizesByRange(
shuffleId: Int,
startMapIndex: Int,
endMapIndex: Int,
startPartition: Int,
endPartition: Int): Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])]
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])]
Comment thread
Ngone51 marked this conversation as resolved.
Outdated

/**
* Deletes map output status information for the specified shuffle stage.
Expand Down Expand Up @@ -737,35 +721,21 @@ private[spark] class MapOutputTrackerMaster(
// Get blocks sizes by executor Id. Note that zero-sized blocks are excluded in the result.
// This method is only called in local-mode.
def getMapSizesByExecutorId(
shuffleId: Int,
startPartition: Int,
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
logDebug(s"Fetching outputs for shuffle $shuffleId, partitions $startPartition-$endPartition")
shuffleStatuses.get(shuffleId) match {
case Some (shuffleStatus) =>
shuffleStatus.withMapStatuses { statuses =>
MapOutputTracker.convertMapStatuses(
shuffleId, startPartition, endPartition, statuses, 0, shuffleStatus.mapStatuses.length)
}
case None =>
Iterator.empty
}
}

override def getMapSizesByRange(
shuffleId: Int,
startMapIndex: Int,
endMapIndex: Int,
startPartition: Int,
endPartition: Int): Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
logDebug(s"Fetching outputs for shuffle $shuffleId, mappers $startMapIndex-$endMapIndex" +
s"partitions $startPartition-$endPartition")
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
logDebug(s"Fetching outputs for shuffle $shuffleId")
shuffleStatuses.get(shuffleId) match {
case Some(shuffleStatus) =>
case Some (shuffleStatus) =>
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
shuffleStatus.withMapStatuses { statuses =>
val endMapIndex0 = if (endMapIndex == Int.MaxValue) statuses.length else endMapIndex
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
logDebug(s"Convert map statuses for shuffle $shuffleId, " +
s"partitions $startPartition-$endPartition, mappers $startMapIndex-$endMapIndex0")
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
MapOutputTracker.convertMapStatuses(
shuffleId, startPartition, endPartition, statuses, startMapIndex, endMapIndex)
shuffleId, startPartition, endPartition, statuses, startMapIndex, endMapIndex0)
}
case None =>
Iterator.empty
Expand Down Expand Up @@ -800,35 +770,20 @@ private[spark] class MapOutputTrackerWorker(conf: SparkConf) extends MapOutputTr

// Get blocks sizes by executor Id. Note that zero-sized blocks are excluded in the result.
override def getMapSizesByExecutorId(
shuffleId: Int,
startPartition: Int,
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
logDebug(s"Fetching outputs for shuffle $shuffleId, partitions $startPartition-$endPartition")
val statuses = getStatuses(shuffleId, conf)
try {
MapOutputTracker.convertMapStatuses(
shuffleId, startPartition, endPartition, statuses, 0, statuses.length)
} catch {
case e: MetadataFetchFailedException =>
// We experienced a fetch failure so our mapStatuses cache is outdated; clear it:
mapStatuses.clear()
throw e
}
}

override def getMapSizesByRange(
shuffleId: Int,
startMapIndex: Int,
endMapIndex: Int,
startPartition: Int,
endPartition: Int): Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
logDebug(s"Fetching outputs for shuffle $shuffleId, mappers $startMapIndex-$endMapIndex" +
s"partitions $startPartition-$endPartition")
endPartition: Int)
: Iterator[(BlockManagerId, Seq[(BlockId, Long, Int)])] = {
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
logDebug(s"Fetching outputs for shuffle $shuffleId")
val statuses = getStatuses(shuffleId, conf)
try {
val endMapIndex0 = if (endMapIndex == Int.MaxValue) statuses.length else endMapIndex
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
logDebug(s"Convert map statuses for shuffle $shuffleId, " +
s"partitions $startPartition-$endPartition, mappers $startMapIndex-$endMapIndex0")
Comment thread
Ngone51 marked this conversation as resolved.
Outdated
MapOutputTracker.convertMapStatuses(
shuffleId, startPartition, endPartition, statuses, startMapIndex, endMapIndex)
shuffleId, startPartition, endPartition, statuses, startMapIndex, endMapIndex0)
} catch {
case e: MetadataFetchFailedException =>
// We experienced a fetch failure so our mapStatuses cache is outdated; clear it:
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/org/apache/spark/rdd/CoGroupedRDD.scala
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,8 @@ class CoGroupedRDD[K: ClassTag](
val metrics = context.taskMetrics().createTempShuffleReadMetrics()
val it = SparkEnv.get.shuffleManager
.getReader(
shuffleDependency.shuffleHandle, split.index, split.index + 1, context, metrics)
shuffleDependency.shuffleHandle, 0, Int.MaxValue,
split.index, split.index + 1, context, metrics)
.read()
rddIterators += ((it, depNum))
}
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/org/apache/spark/rdd/ShuffledRDD.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,8 @@ class ShuffledRDD[K: ClassTag, V: ClassTag, C: ClassTag](
val dep = dependencies.head.asInstanceOf[ShuffleDependency[K, V, C]]
val metrics = context.taskMetrics().createTempShuffleReadMetrics()
SparkEnv.get.shuffleManager.getReader(
dep.shuffleHandle, split.index, split.index + 1, context, metrics)
dep.shuffleHandle, 0, Int.MaxValue,
split.index, split.index + 1, context, metrics)
.read()
.asInstanceOf[Iterator[(K, C)]]
}
Expand Down
10 changes: 3 additions & 7 deletions core/src/main/scala/org/apache/spark/rdd/SubtractedRDD.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,7 @@ import scala.collection.JavaConverters._
import scala.collection.mutable.ArrayBuffer
import scala.reflect.ClassTag

import org.apache.spark.Dependency
import org.apache.spark.OneToOneDependency
import org.apache.spark.Partition
import org.apache.spark.Partitioner
import org.apache.spark.ShuffleDependency
import org.apache.spark.SparkEnv
import org.apache.spark.TaskContext
import org.apache.spark.{Dependency, MapOutputTracker, OneToOneDependency, Partition, Partitioner, ShuffleDependency, SparkEnv, TaskContext}
Comment thread
Ngone51 marked this conversation as resolved.
Outdated

/**
* An optimized version of cogroup for set difference/subtraction.
Expand Down Expand Up @@ -111,6 +105,8 @@ private[spark] class SubtractedRDD[K: ClassTag, V: ClassTag, W: ClassTag](
val iter = SparkEnv.get.shuffleManager
.getReader(
shuffleDependency.shuffleHandle,
0,
Int.MaxValue,
partition.index,
partition.index + 1,
context,
Expand Down
19 changes: 6 additions & 13 deletions core/src/main/scala/org/apache/spark/shuffle/ShuffleManager.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.spark.shuffle

import org.apache.spark.{ShuffleDependency, TaskContext}
import org.apache.spark.scheduler.MapStatus

/**
* Pluggable interface for shuffle systems. A ShuffleManager is created in SparkEnv on the driver
Expand All @@ -43,23 +44,15 @@ private[spark] trait ShuffleManager {
context: TaskContext,
metrics: ShuffleWriteMetricsReporter): ShuffleWriter[K, V]

/**
* Get a reader for a range of reduce partitions (startPartition to endPartition-1, inclusive).
* Called on executors by reduce tasks.
*/
def getReader[K, C](
Comment thread
Ngone51 marked this conversation as resolved.
handle: ShuffleHandle,
startPartition: Int,
endPartition: Int,
context: TaskContext,
metrics: ShuffleReadMetricsReporter): ShuffleReader[K, C]

/**
* Get a reader for a range of reduce partitions (startPartition to endPartition-1, inclusive) to
* read from map output (startMapIndex to endMapIndex - 1, inclusive).
* read from a range of map outputs(startMapIndex to endMapIndex-1, inclusive).
* If endMapIndex=Int.MaxValue, the real endMapIndex will be changed to the length of total map
* outputs of the shuffle in `getMapSizesByExecutorId`.
*
* Called on executors by reduce tasks.
*/
def getReaderForRange[K, C](
def getReader[K, C](
handle: ShuffleHandle,
startMapIndex: Int,
endMapIndex: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import scala.collection.JavaConverters._

import org.apache.spark._
import org.apache.spark.internal.{config, Logging}
import org.apache.spark.scheduler.MapStatus
import org.apache.spark.shuffle._
import org.apache.spark.shuffle.api.{ShuffleDataIO, ShuffleExecutorComponents}
import org.apache.spark.util.Utils
Expand Down Expand Up @@ -115,31 +116,22 @@ private[spark] class SortShuffleManager(conf: SparkConf) extends ShuffleManager
}

/**
* Get a reader for a range of reduce partitions (startPartition to endPartition-1, inclusive).
* Get a reader for a range of reduce partitions (startPartition to endPartition-1, inclusive) to
* read from a range of map outputs(startMapIndex to endMapIndex-1, inclusive).
* If endMapIndex=Int.MaxValue, the real endMapIndex will be changed to the length of total map
* outputs of the shuffle in `getMapSizesByExecutorId`.
*
* Called on executors by reduce tasks.
*/
override def getReader[K, C](
handle: ShuffleHandle,
startPartition: Int,
endPartition: Int,
context: TaskContext,
metrics: ShuffleReadMetricsReporter): ShuffleReader[K, C] = {
val blocksByAddress = SparkEnv.get.mapOutputTracker.getMapSizesByExecutorId(
handle.shuffleId, startPartition, endPartition)
new BlockStoreShuffleReader(
handle.asInstanceOf[BaseShuffleHandle[K, _, C]], blocksByAddress, context, metrics,
shouldBatchFetch = canUseBatchFetch(startPartition, endPartition, context))
}

override def getReaderForRange[K, C](
handle: ShuffleHandle,
startMapIndex: Int,
endMapIndex: Int,
startPartition: Int,
endPartition: Int,
context: TaskContext,
metrics: ShuffleReadMetricsReporter): ShuffleReader[K, C] = {
val blocksByAddress = SparkEnv.get.mapOutputTracker.getMapSizesByRange(
val blocksByAddress = SparkEnv.get.mapOutputTracker.getMapSizesByExecutorId(
handle.shuffleId, startMapIndex, endMapIndex, startPartition, endPartition)
new BlockStoreShuffleReader(
handle.asInstanceOf[BaseShuffleHandle[K, _, C]], blocksByAddress, context, metrics,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ class MapOutputTrackerSuite extends SparkFunSuite {
tracker.registerMapOutput(10, 1, MapStatus(BlockManagerId("b", "hostB", 1000),
Array(size10000, size0, size1000, size0), 6))
assert(tracker.containsShuffle(10))
assert(tracker.getMapSizesByExecutorId(10, 0, 4).toSeq ===
assert(tracker.getMapSizesByExecutorId(10, 0, 2, 0, 4).toSeq ===
Seq(
(BlockManagerId("a", "hostA", 1000),
Seq((ShuffleBlockId(10, 5, 1), size1000, 0),
Expand Down
3 changes: 2 additions & 1 deletion core/src/test/scala/org/apache/spark/ShuffleSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ abstract class ShuffleSuite extends SparkFunSuite with Matchers with LocalSparkC
val taskContext = new TaskContextImpl(
1, 0, 0, 2L, 0, taskMemoryManager, new Properties, metricsSystem)
val metrics = taskContext.taskMetrics.createTempShuffleReadMetrics()
val reader = manager.getReader[Int, Int](shuffleHandle, 0, 1, taskContext, metrics)
val reader = manager.getReader[Int, Int](shuffleHandle, 0, Int.MaxValue,
0, 1, taskContext, metrics)
TaskContext.unset()
val readData = reader.read().toIndexedSeq
assert(readData === data1.toIndexedSeq || readData === data2.toIndexedSeq)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,8 @@ class CustomShuffledRDD[K, V, C](
val part = p.asInstanceOf[CustomShuffledRDDPartition]
val metrics = context.taskMetrics().createTempShuffleReadMetrics()
SparkEnv.get.shuffleManager.getReader(
dependency.shuffleHandle, part.startIndexInParent, part.endIndexInParent, context, metrics)
dependency.shuffleHandle, 0, Int.MaxValue, part.startIndexInParent,
part.endIndexInParent, context, metrics)
.read()
.asInstanceOf[Iterator[(K, C)]]
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class BlockStoreShuffleReaderSuite extends SparkFunSuite with LocalSparkContext
// shuffle data to read.
val mapOutputTracker = mock(classOf[MapOutputTracker])
when(mapOutputTracker.getMapSizesByExecutorId(
shuffleId, reduceId, reduceId + 1)).thenReturn {
shuffleId, 0, numMaps, reduceId, reduceId + 1)).thenReturn {
// Test a scenario where all data is local, to avoid creating a bunch of additional mocks
// for the code to read data over the network.
val shuffleBlockIdsAndSizes = (0 until numMaps).map { mapId =>
Expand Down Expand Up @@ -132,7 +132,7 @@ class BlockStoreShuffleReaderSuite extends SparkFunSuite with LocalSparkContext
val taskContext = TaskContext.empty()
val metrics = taskContext.taskMetrics.createTempShuffleReadMetrics()
val blocksByAddress = mapOutputTracker.getMapSizesByExecutorId(
shuffleId, reduceId, reduceId + 1)
shuffleId, 0, numMaps, reduceId, reduceId + 1)
val shuffleReader = new BlockStoreShuffleReader(
shuffleHandle,
blocksByAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,13 +185,15 @@ class ShuffledRowRDD(
case CoalescedPartitionSpec(startReducerIndex, endReducerIndex) =>
SparkEnv.get.shuffleManager.getReader(
dependency.shuffleHandle,
0,
Int.MaxValue,
startReducerIndex,
endReducerIndex,
context,
sqlMetricsReporter)

case PartialReducerPartitionSpec(reducerIndex, startMapIndex, endMapIndex, _) =>
SparkEnv.get.shuffleManager.getReaderForRange(
SparkEnv.get.shuffleManager.getReader(
dependency.shuffleHandle,
startMapIndex,
endMapIndex,
Expand All @@ -201,7 +203,7 @@ class ShuffledRowRDD(
sqlMetricsReporter)

case PartialMapperPartitionSpec(mapIndex, startReducerIndex, endReducerIndex) =>
SparkEnv.get.shuffleManager.getReaderForRange(
SparkEnv.get.shuffleManager.getReader(
dependency.shuffleHandle,
mapIndex,
mapIndex + 1,
Expand Down