Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4e31bb7
Use map output statistices to improve global limit's parallelism.
viirya Jan 23, 2017
b049cc4
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Feb 4, 2017
45a1fcb
Use Long for number of outputs. Turn to the approach of calculating n…
viirya Feb 27, 2017
e9679ba
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Mar 1, 2017
1a56252
Rebased with latest change.
viirya Mar 1, 2017
df44243
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Mar 7, 2017
2d37598
Changed Limit outputs different results. It affects the test case out…
viirya Mar 7, 2017
b8a2275
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Apr 11, 2017
867a93d
Address comments.
viirya May 11, 2017
55ee6b0
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya May 18, 2017
8f779ac
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Jun 21, 2017
f2a7aac
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Sep 11, 2017
7598337
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Oct 31, 2017
e53648e
ShuffleExchange becomes ShuffleExchangeExec now.
viirya Oct 31, 2017
062b8fd
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya May 7, 2018
47f6031
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya May 7, 2018
a691e88
Fix merging conflict.
viirya May 7, 2018
5594bf9
Avoid evenly scanning partitions when child output has ordering.
viirya May 10, 2018
c9c8be6
Some refactoring.
viirya May 10, 2018
ca00701
Disable global limit optimization in limit sql query test.
viirya Jun 22, 2018
21b6948
Use array instead of map.
viirya Jun 22, 2018
59a3029
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Jun 22, 2018
4b443cc
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Jun 22, 2018
1ff1fa5
Resolve merging issue.
viirya Jun 22, 2018
a737573
Address comment.
viirya Jun 22, 2018
b0cca1a
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Jun 22, 2018
f24171e
Address comment.
viirya Jun 23, 2018
2d522b4
Use orgPartition.numPartitions.
viirya Jun 26, 2018
9792220
Use childRDD.
viirya Jun 26, 2018
19d7d75
Use writeMetrics.recordsWritten.
viirya Jun 28, 2018
d05c144
Revert unused change.
viirya Jul 24, 2018
69513d1
Merge remote-tracking branch 'upstream/master' into improve-global-li…
viirya Aug 4, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public void write(Iterator<Product2<K, V>> records) throws IOException {
if (!records.hasNext()) {
partitionLengths = new long[numPartitions];
shuffleBlockResolver.writeIndexFileAndCommit(shuffleId, mapId, partitionLengths, null);
mapStatus = MapStatus$.MODULE$.apply(blockManager.shuffleServerId(), partitionLengths);
mapStatus = MapStatus$.MODULE$.apply(blockManager.shuffleServerId(), partitionLengths, 0);
return;
}
final SerializerInstance serInstance = serializer.newInstance();
Expand All @@ -146,10 +146,12 @@ public void write(Iterator<Product2<K, V>> records) throws IOException {
// included in the shuffle write time.
writeMetrics.incWriteTime(System.nanoTime() - openStartTime);

int numOfRecords = 0;
while (records.hasNext()) {
final Product2<K, V> record = records.next();
final K key = record._1();
partitionWriters[partitioner.getPartition(key)].write(key, record._2());
numOfRecords += 1;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere, simply use writeMetrics._recordsWritten instead of adding numOfRecords ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, I think it is fine. However, maybe I miss it, but I can't find SortShuffleWriter has updated writeMetrics_recordsWritten?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are introducing numOfRecords because (as you say) some code paths are not updating the metric.
Instead of working around the bug and cluttering code, it is better to fix it cleanly (unless there is some design issue or more complicated issue).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To verify it, I ran a test locally. Looks like writeMetrics_recordsWritten is well updated in SortShuffleWriter path too. So I will replace numOfRecords with writeMetrics_recordsWritten.

}

for (int i = 0; i < numPartitions; i++) {
Expand All @@ -168,7 +170,8 @@ public void write(Iterator<Product2<K, V>> records) throws IOException {
logger.error("Error while deleting temp file {}", tmp.getAbsolutePath());
}
}
mapStatus = MapStatus$.MODULE$.apply(blockManager.shuffleServerId(), partitionLengths);
mapStatus = MapStatus$.MODULE$.apply(
blockManager.shuffleServerId(), partitionLengths, numOfRecords);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ public class UnsafeShuffleWriter<K, V> extends ShuffleWriter<K, V> {
@Nullable private ShuffleExternalSorter sorter;
private long peakMemoryUsedBytes = 0;

private int numOfRecords = 0;

/** Subclass of ByteArrayOutputStream that exposes `buf` directly. */
private static final class MyByteArrayOutputStream extends ByteArrayOutputStream {
MyByteArrayOutputStream(int size) { super(size); }
Expand Down Expand Up @@ -165,6 +167,7 @@ public void write(scala.collection.Iterator<Product2<K, V>> records) throws IOEx
try {
while (records.hasNext()) {
insertRecordIntoSorter(records.next());
numOfRecords += 1;
}
closeAndWriteOutput();
success = true;
Expand Down Expand Up @@ -227,7 +230,8 @@ void closeAndWriteOutput() throws IOException {
logger.error("Error while deleting temp file {}", tmp.getAbsolutePath());
}
}
mapStatus = MapStatus$.MODULE$.apply(blockManager.shuffleServerId(), partitionLengths);
mapStatus = MapStatus$.MODULE$.apply(
blockManager.shuffleServerId(), partitionLengths, numOfRecords);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,9 @@ package org.apache.spark
* @param shuffleId ID of the shuffle
* @param bytesByPartitionId approximate number of output bytes for each map output partition
* (may be inexact due to use of compressed map statuses)
* @param numberOfOutput number of output for each pre-map output partition

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does pre-map output partition mean? numberOfOutput is the same name in MapStatus, rename it recordsByPartitionId?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is different with bytesByPartitionId. It is not the number of records for each reducer. Rather said, it is the number of records for each map task.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename it to recordsByMapTask.

*/
private[spark] class MapOutputStatistics(val shuffleId: Int, val bytesByPartitionId: Array[Long])
private[spark] class MapOutputStatistics(
val shuffleId: Int,
val bytesByPartitionId: Array[Long],
val numberOfOutput: Array[Int])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, maybe Long is better.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Use Long now

6 changes: 4 additions & 2 deletions core/src/main/scala/org/apache/spark/MapOutputTracker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -156,12 +156,14 @@ private[spark] abstract class MapOutputTracker(conf: SparkConf) extends Logging
// Synchronize on the returned array because, on the driver, it gets mutated in place
statuses.synchronized {
val totalSizes = new Array[Long](dep.partitioner.numPartitions)
for (s <- statuses) {
val numberOfOutput = new Array[Int](statuses.length)
statuses.zipWithIndex.map { case (s, index) =>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

map -> foreach

for (i <- 0 until totalSizes.length) {
totalSizes(i) += s.getSizeForBlock(i)
}
numberOfOutput(index) = s.numberOfOutput
}
new MapOutputStatistics(dep.shuffleId, totalSizes)
new MapOutputStatistics(dep.shuffleId, totalSizes, numberOfOutput)
}
}

Expand Down
40 changes: 28 additions & 12 deletions core/src/main/scala/org/apache/spark/scheduler/MapStatus.scala
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import org.apache.spark.util.Utils

/**
* Result returned by a ShuffleMapTask to a scheduler. Includes the block manager address that the
* task ran on as well as the sizes of outputs for each reducer, for passing on to the reduce tasks.
* task ran on, the sizes of outputs for each reducer, and the number of outputs of the map task,
* for passing on to the reduce tasks.
*/
private[spark] sealed trait MapStatus {
/** Location where this task was run. */
Expand All @@ -39,16 +40,18 @@ private[spark] sealed trait MapStatus {
* necessary for correctness, since block fetchers are allowed to skip zero-size blocks.
*/
def getSizeForBlock(reduceId: Int): Long

def numberOfOutput: Int

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The number of output may be greater than 2G?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Long now.

}


private[spark] object MapStatus {

def apply(loc: BlockManagerId, uncompressedSizes: Array[Long]): MapStatus = {
def apply(loc: BlockManagerId, uncompressedSizes: Array[Long], numOutput: Int): MapStatus = {
if (uncompressedSizes.length > 2000) {
HighlyCompressedMapStatus(loc, uncompressedSizes)
HighlyCompressedMapStatus(loc, uncompressedSizes, numOutput)
} else {
new CompressedMapStatus(loc, uncompressedSizes)
new CompressedMapStatus(loc, uncompressedSizes, numOutput)
}
}

Expand Down Expand Up @@ -91,29 +94,34 @@ private[spark] object MapStatus {
*/
private[spark] class CompressedMapStatus(
private[this] var loc: BlockManagerId,
private[this] var compressedSizes: Array[Byte])
private[this] var compressedSizes: Array[Byte],
private[this] var numOutput: Int)
extends MapStatus with Externalizable {

protected def this() = this(null, null.asInstanceOf[Array[Byte]]) // For deserialization only
protected def this() = this(null, null.asInstanceOf[Array[Byte]], -1) // For deserialization only

def this(loc: BlockManagerId, uncompressedSizes: Array[Long]) {
this(loc, uncompressedSizes.map(MapStatus.compressSize))
def this(loc: BlockManagerId, uncompressedSizes: Array[Long], numOutput: Int) {
this(loc, uncompressedSizes.map(MapStatus.compressSize), numOutput)
}

override def location: BlockManagerId = loc

override def numberOfOutput: Int = numOutput

override def getSizeForBlock(reduceId: Int): Long = {
MapStatus.decompressSize(compressedSizes(reduceId))
}

override def writeExternal(out: ObjectOutput): Unit = Utils.tryOrIOException {
loc.writeExternal(out)
out.writeInt(numOutput)
out.writeInt(compressedSizes.length)
out.write(compressedSizes)
}

override def readExternal(in: ObjectInput): Unit = Utils.tryOrIOException {
loc = BlockManagerId(in)
numOutput = in.readInt()
val len = in.readInt()
compressedSizes = new Array[Byte](len)
in.readFully(compressedSizes)
Expand All @@ -133,17 +141,20 @@ private[spark] class HighlyCompressedMapStatus private (
private[this] var loc: BlockManagerId,
private[this] var numNonEmptyBlocks: Int,
private[this] var emptyBlocks: RoaringBitmap,
private[this] var avgSize: Long)
private[this] var avgSize: Long,
private[this] var numOutput: Int)
extends MapStatus with Externalizable {

// loc could be null when the default constructor is called during deserialization
require(loc == null || avgSize > 0 || numNonEmptyBlocks == 0,
"Average size can only be zero for map stages that produced no output")

protected def this() = this(null, -1, null, -1) // For deserialization only
protected def this() = this(null, -1, null, -1, -1) // For deserialization only

override def location: BlockManagerId = loc

override def numberOfOutput: Int = numOutput

override def getSizeForBlock(reduceId: Int): Long = {
if (emptyBlocks.contains(reduceId)) {
0
Expand All @@ -154,20 +165,25 @@ private[spark] class HighlyCompressedMapStatus private (

override def writeExternal(out: ObjectOutput): Unit = Utils.tryOrIOException {
loc.writeExternal(out)
out.writeInt(numOutput)
emptyBlocks.writeExternal(out)
out.writeLong(avgSize)
}

override def readExternal(in: ObjectInput): Unit = Utils.tryOrIOException {
loc = BlockManagerId(in)
numOutput = in.readInt()
emptyBlocks = new RoaringBitmap()
emptyBlocks.readExternal(in)
avgSize = in.readLong()
}
}

private[spark] object HighlyCompressedMapStatus {
def apply(loc: BlockManagerId, uncompressedSizes: Array[Long]): HighlyCompressedMapStatus = {
def apply(
loc: BlockManagerId,
uncompressedSizes: Array[Long],
numOutput: Int): HighlyCompressedMapStatus = {
// We must keep track of which blocks are empty so that we don't report a zero-sized
// block as being non-empty (or vice-versa) when using the average block size.
var i = 0
Expand Down Expand Up @@ -195,6 +211,6 @@ private[spark] object HighlyCompressedMapStatus {
}
emptyBlocks.trim()
emptyBlocks.runOptimize()
new HighlyCompressedMapStatus(loc, numNonEmptyBlocks, emptyBlocks, avgSize)
new HighlyCompressedMapStatus(loc, numNonEmptyBlocks, emptyBlocks, avgSize, numOutput)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ private[spark] class SortShuffleWriter[K, V, C](
new ExternalSorter[K, V, V](
context, aggregator = None, Some(dep.partitioner), ordering = None, dep.serializer)
}
sorter.insertAll(records)
val numOfRecords = sorter.insertAll(records)

// Don't bother including the time to open the merged output file in the shuffle write time,
// because it just opens a single file, so is typically too fast to measure accurately
Expand All @@ -71,7 +71,7 @@ private[spark] class SortShuffleWriter[K, V, C](
val blockId = ShuffleBlockId(dep.shuffleId, mapId, IndexShuffleBlockResolver.NOOP_REDUCE_ID)
val partitionLengths = sorter.writePartitionedFile(blockId, tmp)
shuffleBlockResolver.writeIndexFileAndCommit(dep.shuffleId, mapId, partitionLengths, tmp)
mapStatus = MapStatus(blockManager.shuffleServerId, partitionLengths)
mapStatus = MapStatus(blockManager.shuffleServerId, partitionLengths, numOfRecords)
} finally {
if (tmp.exists() && !tmp.delete()) {
logError(s"Error while deleting temp file ${tmp.getAbsolutePath}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,12 @@ private[spark] class ExternalSorter[K, V, C](
*/
private[spark] def numSpills: Int = spills.size

def insertAll(records: Iterator[Product2[K, V]]): Unit = {
def insertAll(records: Iterator[Product2[K, V]]): Int = {
// TODO: stop combining if we find that the reduction factor isn't high
val shouldCombine = aggregator.isDefined

var numOfRecords: Int = 0

if (shouldCombine) {
// Combine values in-memory first using our AppendOnlyMap
val mergeValue = aggregator.get.mergeValue
Expand All @@ -193,6 +195,7 @@ private[spark] class ExternalSorter[K, V, C](
kv = records.next()
map.changeValue((getPartition(kv._1), kv._1), update)
maybeSpillCollection(usingMap = true)
numOfRecords += 1
}
} else {
// Stick values into our buffer
Expand All @@ -201,8 +204,10 @@ private[spark] class ExternalSorter[K, V, C](
val kv = records.next()
buffer.insert(getPartition(kv._1), kv._1, kv._2.asInstanceOf[C])
maybeSpillCollection(usingMap = false)
numOfRecords += 1
}
}
numOfRecords
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,7 @@ public void writeEmptyIterator() throws Exception {
writer.write(Iterators.<Product2<Object, Object>>emptyIterator());
final Option<MapStatus> mapStatus = writer.stop(true);
assertTrue(mapStatus.isDefined());
assertEquals(0, mapStatus.get().numberOfOutput());
assertTrue(mergedOutputFile.exists());
assertArrayEquals(new long[NUM_PARTITITONS], partitionSizesInMergedFile);
assertEquals(0, taskMetrics.shuffleWriteMetrics().recordsWritten());
Expand All @@ -265,6 +266,7 @@ public void writeWithoutSpilling() throws Exception {
writer.write(dataToWrite.iterator());
final Option<MapStatus> mapStatus = writer.stop(true);
assertTrue(mapStatus.isDefined());
assertEquals(NUM_PARTITITONS, mapStatus.get().numberOfOutput());
assertTrue(mergedOutputFile.exists());

long sumOfPartitionSizes = 0;
Expand Down
24 changes: 12 additions & 12 deletions core/src/test/scala/org/apache/spark/MapOutputTrackerSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ class MapOutputTrackerSuite extends SparkFunSuite {
val size1000 = MapStatus.decompressSize(MapStatus.compressSize(1000L))
val size10000 = MapStatus.decompressSize(MapStatus.compressSize(10000L))
tracker.registerMapOutput(10, 0, MapStatus(BlockManagerId("a", "hostA", 1000),
Array(1000L, 10000L)))
Array(1000L, 10000L), 10))
tracker.registerMapOutput(10, 1, MapStatus(BlockManagerId("b", "hostB", 1000),
Array(10000L, 1000L)))
Array(10000L, 1000L), 10))
val statuses = tracker.getMapSizesByExecutorId(10, 0)
assert(statuses.toSet ===
Seq((BlockManagerId("a", "hostA", 1000), ArrayBuffer((ShuffleBlockId(10, 0, 0), size1000))),
Expand All @@ -83,9 +83,9 @@ class MapOutputTrackerSuite extends SparkFunSuite {
val compressedSize1000 = MapStatus.compressSize(1000L)
val compressedSize10000 = MapStatus.compressSize(10000L)
tracker.registerMapOutput(10, 0, MapStatus(BlockManagerId("a", "hostA", 1000),
Array(compressedSize1000, compressedSize10000)))
Array(compressedSize1000, compressedSize10000), 10))
tracker.registerMapOutput(10, 1, MapStatus(BlockManagerId("b", "hostB", 1000),
Array(compressedSize10000, compressedSize1000)))
Array(compressedSize10000, compressedSize1000), 10))
assert(tracker.containsShuffle(10))
assert(tracker.getMapSizesByExecutorId(10, 0).nonEmpty)
assert(0 == tracker.getNumCachedSerializedBroadcast)
Expand All @@ -106,9 +106,9 @@ class MapOutputTrackerSuite extends SparkFunSuite {
val compressedSize1000 = MapStatus.compressSize(1000L)
val compressedSize10000 = MapStatus.compressSize(10000L)
tracker.registerMapOutput(10, 0, MapStatus(BlockManagerId("a", "hostA", 1000),
Array(compressedSize1000, compressedSize1000, compressedSize1000)))
Array(compressedSize1000, compressedSize1000, compressedSize1000), 10))
tracker.registerMapOutput(10, 1, MapStatus(BlockManagerId("b", "hostB", 1000),
Array(compressedSize10000, compressedSize1000, compressedSize1000)))
Array(compressedSize10000, compressedSize1000, compressedSize1000), 10))

assert(0 == tracker.getNumCachedSerializedBroadcast)
// As if we had two simultaneous fetch failures
Expand Down Expand Up @@ -144,7 +144,7 @@ class MapOutputTrackerSuite extends SparkFunSuite {

val size1000 = MapStatus.decompressSize(MapStatus.compressSize(1000L))
masterTracker.registerMapOutput(10, 0, MapStatus(
BlockManagerId("a", "hostA", 1000), Array(1000L)))
BlockManagerId("a", "hostA", 1000), Array(1000L), 10))
masterTracker.incrementEpoch()
slaveTracker.updateEpoch(masterTracker.getEpoch)
assert(slaveTracker.getMapSizesByExecutorId(10, 0) ===
Expand Down Expand Up @@ -180,7 +180,7 @@ class MapOutputTrackerSuite extends SparkFunSuite {
// Message size should be ~123B, and no exception should be thrown
masterTracker.registerShuffle(10, 1)
masterTracker.registerMapOutput(10, 0, MapStatus(
BlockManagerId("88", "mph", 1000), Array.fill[Long](10)(0)))
BlockManagerId("88", "mph", 1000), Array.fill[Long](10)(0), 0))
val senderAddress = RpcAddress("localhost", 12345)
val rpcCallContext = mock(classOf[RpcCallContext])
when(rpcCallContext.senderAddress).thenReturn(senderAddress)
Expand Down Expand Up @@ -214,11 +214,11 @@ class MapOutputTrackerSuite extends SparkFunSuite {
// on hostB with output size 3
tracker.registerShuffle(10, 3)
tracker.registerMapOutput(10, 0, MapStatus(BlockManagerId("a", "hostA", 1000),
Array(2L)))
Array(2L), 1))
tracker.registerMapOutput(10, 1, MapStatus(BlockManagerId("a", "hostA", 1000),
Array(2L)))
Array(2L), 1))
tracker.registerMapOutput(10, 2, MapStatus(BlockManagerId("b", "hostB", 1000),
Array(3L)))
Array(3L), 1))

// When the threshold is 50%, only host A should be returned as a preferred location
// as it has 4 out of 7 bytes of output.
Expand Down Expand Up @@ -259,7 +259,7 @@ class MapOutputTrackerSuite extends SparkFunSuite {
masterTracker.registerShuffle(20, 100)
(0 until 100).foreach { i =>
masterTracker.registerMapOutput(20, i, new CompressedMapStatus(
BlockManagerId("999", "mps", 1000), Array.fill[Long](4000000)(0)))
BlockManagerId("999", "mps", 1000), Array.fill[Long](4000000)(0), 0))
}
val senderAddress = RpcAddress("localhost", 12345)
val rpcCallContext = mock(classOf[RpcCallContext])
Expand Down
1 change: 1 addition & 0 deletions core/src/test/scala/org/apache/spark/ShuffleSuite.scala
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ abstract class ShuffleSuite extends SparkFunSuite with Matchers with LocalSparkC
assert(mapOutput2.isDefined)
assert(mapOutput1.get.location === mapOutput2.get.location)
assert(mapOutput1.get.getSizeForBlock(0) === mapOutput1.get.getSizeForBlock(0))
assert(mapOutput1.get.numberOfOutput === mapOutput2.get.numberOfOutput)

// register one of the map outputs -- doesn't matter which one
mapOutput1.foreach { case mapStatus =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2215,7 +2215,7 @@ class DAGSchedulerSuite extends SparkFunSuite with LocalSparkContext with Timeou

object DAGSchedulerSuite {
def makeMapStatus(host: String, reduces: Int, sizes: Byte = 2): MapStatus =
MapStatus(makeBlockManagerId(host), Array.fill[Long](reduces)(sizes))
MapStatus(makeBlockManagerId(host), Array.fill[Long](reduces)(sizes), 1)

def makeBlockManagerId(host: String): BlockManagerId =
BlockManagerId("exec-" + host, host, 12345)
Expand Down
Loading