Skip to content

Commit 7b23ef3

Browse files
author
pgandhi
committed
[SPARK-26755] : Addressing Reviews July 17, 2019
Modifying comment in Scaladoc style and combining two unit tests into one
1 parent 466849e commit 7b23ef3

File tree

2 files changed

+43
-45
lines changed

2 files changed

+43
-45
lines changed

core/src/main/scala/org/apache/spark/scheduler/TaskSetManager.scala

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1043,19 +1043,21 @@ private[spark] object TaskSetManager {
10431043
val TASK_SIZE_TO_WARN_KIB = 1000
10441044
}
10451045

1046-
// Set of pending tasks for various levels of locality: executor, host, rack,
1047-
// noPrefs and anyPrefs. These collections are actually
1048-
// treated as stacks, in which new tasks are added to the end of the
1049-
// ArrayBuffer and removed from the end. This makes it faster to detect
1050-
// tasks that repeatedly fail because whenever a task failed, it is put
1051-
// back at the head of the stack. These collections may contain duplicates
1052-
// for two reasons:
1053-
// (1): Tasks are only removed lazily; when a task is launched, it remains
1054-
// in all the pending lists except the one that it was launched from.
1055-
// (2): Tasks may be re-added to these lists multiple times as a result
1056-
// of failures.
1057-
// Duplicates are handled in dequeueTaskFromList, which ensures that a
1058-
// task hasn't already started running before launching it.
1046+
/**
1047+
* Set of pending tasks for various levels of locality: executor, host, rack,
1048+
* noPrefs and anyPrefs. These collections are actually
1049+
* treated as stacks, in which new tasks are added to the end of the
1050+
* ArrayBuffer and removed from the end. This makes it faster to detect
1051+
* tasks that repeatedly fail because whenever a task failed, it is put
1052+
* back at the head of the stack. These collections may contain duplicates
1053+
* for two reasons:
1054+
* (1): Tasks are only removed lazily; when a task is launched, it remains
1055+
* in all the pending lists except the one that it was launched from.
1056+
* (2): Tasks may be re-added to these lists multiple times as a result
1057+
* of failures.
1058+
* Duplicates are handled in dequeueTaskFromList, which ensures that a
1059+
* task hasn't already started running before launching it.
1060+
*/
10591061
private[scheduler] class PendingTasksByLocality {
10601062

10611063
// Set of pending tasks for each executor.

core/src/test/scala/org/apache/spark/scheduler/TaskSetManagerSuite.scala

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,7 +1658,8 @@ class TaskSetManagerSuite extends SparkFunSuite with LocalSparkContext with Logg
16581658
assert(availableResources(GPU) sameElements Array("0", "1", "2", "3"))
16591659
}
16601660

1661-
test("SPARK-26755 Ensure that a speculative task is submitted only once for execution") {
1661+
test("SPARK-26755 Ensure that a speculative task is submitted only once for execution and" +
1662+
" must also obey original locality preferences") {
16621663
sc = new SparkContext("local", "test")
16631664
sched = new FakeTaskScheduler(sc, ("exec1", "host1"), ("exec2", "host2"))
16641665
val taskSet = FakeTask.createTaskSet(4)
@@ -1682,7 +1683,7 @@ class TaskSetManagerSuite extends SparkFunSuite with LocalSparkContext with Logg
16821683
assert(sched.startedTasks.toSet === Set(0, 1, 2, 3))
16831684
clock.advance(1)
16841685
// Complete the first 2 tasks and leave the other 2 tasks in running
1685-
for (id <- Set(0, 1)) {
1686+
for (id <- Set(0, 2)) {
16861687
manager.handleSuccessfulTask(id, createTaskResult(id, accumUpdatesByTask(id)))
16871688
assert(sched.endedTasks(id) === Success)
16881689
}
@@ -1691,79 +1692,74 @@ class TaskSetManagerSuite extends SparkFunSuite with LocalSparkContext with Logg
16911692
// > 0ms, so advance the clock by 1ms here.
16921693
clock.advance(1)
16931694
assert(manager.checkSpeculatableTasks(0))
1694-
assert(sched.speculativeTasks.toSet === Set(2, 3))
1695-
assert(manager.copiesRunning(2) === 1)
1695+
assert(sched.speculativeTasks.toSet === Set(1, 3))
1696+
assert(manager.copiesRunning(1) === 1)
16961697
assert(manager.copiesRunning(3) === 1)
16971698

16981699
// Offer resource to start the speculative attempt for the running task. We offer more
16991700
// resources, and ensure that speculative tasks get scheduled appropriately -- only one extra
17001701
// copy per speculatable task
17011702
val taskOption2 = manager.resourceOffer("exec1", "host1", NO_PREF)
1702-
val taskOption3 = manager.resourceOffer("exec1", "host1", NO_PREF)
1703+
val taskOption3 = manager.resourceOffer("exec2", "host2", NO_PREF)
17031704
assert(taskOption2.isDefined)
17041705
val task2 = taskOption2.get
1706+
// Ensure that task index 3 is launched on host1 and task index 4 on host2
17051707
assert(task2.index === 3)
17061708
assert(task2.taskId === 4)
17071709
assert(task2.executorId === "exec1")
17081710
assert(task2.attemptNumber === 1)
17091711
assert(taskOption3.isDefined)
17101712
val task3 = taskOption3.get
1711-
assert(task3.index === 2)
1713+
assert(task3.index === 1)
17121714
assert(task3.taskId === 5)
1713-
assert(task3.executorId === "exec1")
1715+
assert(task3.executorId === "exec2")
17141716
assert(task3.attemptNumber === 1)
17151717
clock.advance(1)
17161718
// Running checkSpeculatableTasks again should return false
17171719
assert(!manager.checkSpeculatableTasks(0))
1718-
assert(manager.copiesRunning(2) === 2)
1720+
assert(manager.copiesRunning(1) === 2)
17191721
assert(manager.copiesRunning(3) === 2)
17201722
// Offering additional resources should not lead to any speculative tasks being respawned
17211723
assert(manager.resourceOffer("exec1", "host1", ANY).isEmpty)
17221724
assert(manager.resourceOffer("exec2", "host2", ANY).isEmpty)
17231725
assert(manager.resourceOffer("exec3", "host3", ANY).isEmpty)
1724-
}
17251726

1726-
test("SPARK-26755 Ensure that a speculative task obeys the original locality preferences") {
1727-
sc = new SparkContext("local", "test")
1727+
// Launch a new set of tasks with locality preferences
17281728
sched = new FakeTaskScheduler(sc, ("exec1", "host1"),
17291729
("exec2", "host2"), ("exec3", "host3"), ("exec4", "host4"))
1730-
// Create 3 tasks with locality preferences
1731-
val taskSet = FakeTask.createTaskSet(3,
1730+
val taskSet2 = FakeTask.createTaskSet(3,
17321731
Seq(TaskLocation("host1"), TaskLocation("host3")),
17331732
Seq(TaskLocation("host2")),
17341733
Seq(TaskLocation("host3")))
1735-
// Set the speculation multiplier to be 0 so speculative tasks are launched immediately
1736-
sc.conf.set(config.SPECULATION_MULTIPLIER, 0.0)
1737-
sc.conf.set(config.SPECULATION_ENABLED, true)
1738-
sc.conf.set(config.SPECULATION_QUANTILE, 0.5)
1739-
val clock = new ManualClock()
1740-
val manager = new TaskSetManager(sched, taskSet, MAX_TASK_FAILURES, clock = clock)
1741-
val accumUpdatesByTask: Array[Seq[AccumulatorV2[_, _]]] = taskSet.tasks.map { task =>
1734+
val clock2 = new ManualClock()
1735+
val manager2 = new TaskSetManager(sched, taskSet2, MAX_TASK_FAILURES, clock = clock2)
1736+
val accumUpdatesByTask2: Array[Seq[AccumulatorV2[_, _]]] = taskSet2.tasks.map { task =>
17421737
task.metrics.internalAccums
17431738
}
1739+
17441740
// Offer resources for 3 tasks to start
17451741
Seq("exec1" -> "host1", "exec2" -> "host2", "exec3" -> "host3").foreach { case (exec, host) =>
1746-
val taskOption = manager.resourceOffer(exec, host, NO_PREF)
1742+
val taskOption = manager2.resourceOffer(exec, host, NO_PREF)
17471743
assert(taskOption.isDefined)
17481744
assert(taskOption.get.executorId === exec)
17491745
}
17501746
assert(sched.startedTasks.toSet === Set(0, 1, 2))
1751-
clock.advance(1)
1747+
clock2.advance(1)
17521748
// Finish one task and mark the others as speculatable
1753-
manager.handleSuccessfulTask(2, createTaskResult(2, accumUpdatesByTask(2)))
1749+
manager2.handleSuccessfulTask(2, createTaskResult(2, accumUpdatesByTask2(2)))
17541750
assert(sched.endedTasks(2) === Success)
1755-
clock.advance(1)
1756-
assert(manager.checkSpeculatableTasks(0))
1751+
clock2.advance(1)
1752+
assert(manager2.checkSpeculatableTasks(0))
17571753
assert(sched.speculativeTasks.toSet === Set(0, 1))
17581754
// Ensure that the speculatable tasks obey the original locality preferences
1759-
assert(manager.resourceOffer("exec4", "host4", NODE_LOCAL).isEmpty)
1760-
assert(manager.resourceOffer("exec2", "host2", NODE_LOCAL).isEmpty)
1761-
assert(manager.resourceOffer("exec3", "host3", NODE_LOCAL).isDefined)
1762-
assert(manager.resourceOffer("exec4", "host4", ANY).isDefined)
1755+
assert(manager2.resourceOffer("exec4", "host4", NODE_LOCAL).isEmpty)
1756+
assert(manager2.resourceOffer("exec2", "host2", NODE_LOCAL).isEmpty)
1757+
assert(manager2.resourceOffer("exec3", "host3", NODE_LOCAL).isDefined)
1758+
assert(manager2.resourceOffer("exec4", "host4", ANY).isDefined)
17631759
// Since, all speculatable tasks have been launched, making another offer
17641760
// should not schedule any more tasks
1765-
assert(manager.resourceOffer("exec1", "host1", ANY).isEmpty)
1766-
assert(!manager.checkSpeculatableTasks(0))
1767-
assert(manager.resourceOffer("exec1", "host1", ANY).isEmpty)
1761+
assert(manager2.resourceOffer("exec1", "host1", ANY).isEmpty)
1762+
assert(!manager2.checkSpeculatableTasks(0))
1763+
assert(manager2.resourceOffer("exec1", "host1", ANY).isEmpty)
17681764
}
17691765
}

0 commit comments

Comments
 (0)