Github user squito commented on a diff in the pull request:
https://github.com/apache/spark/pull/15644#discussion_r87302653
--- Diff:
core/src/test/scala/org/apache/spark/scheduler/TaskSchedulerImplSuite.scala ---
@@ -282,6 +317,154 @@ class TaskSchedulerImplSuite extends SparkFunSuite
with LocalSparkContext with B
assert(!failedTaskSet)
}
+ /**
+ * Create tasksets, a mock blacklist, and a set of offers commmon to
some tests on taskset
+ * blacklists.
+ */
+ private def taskSetBlacklistSetup(): IndexedSeq[WorkerOffer] = {
+ (0 to 2).foreach {stageId =>
+ val taskSet = FakeTask.createTaskSet(numTasks = 2, stageId =
stageId, stageAttemptId = 0)
+ taskScheduler.submitTasks(taskSet)
+ }
+
+ // Setup our mock blacklist:
+ // * stage 0 is blacklisted on node "host1"
+ // * stage 1 is blacklisted on executor "executor3"
+ // * stage 0, partition 0 is blacklisted on executor 0
+ // Setup some defaults (nothing is blacklisted), then override them
with particulars.
+ // (Later stubs take precedence over earlier ones.)
+ stageToMockTaskSetBlacklist.values.foreach { taskSetBlacklist =>
+
when(taskSetBlacklist.isNodeBlacklistedForTaskSet(anyString())).thenReturn(false)
+
when(taskSetBlacklist.isExecutorBlacklistedForTaskSet(anyString())).thenReturn(false)
+ when(taskSetBlacklist.isExecutorBlacklistedForTask(anyString(),
anyInt())).thenReturn(false)
+ when(taskSetBlacklist.isNodeBlacklistedForTask(anyString(),
anyInt())).thenReturn(false)
+ }
+
when(stageToMockTaskSetBlacklist(0).isNodeBlacklistedForTaskSet("host1")).thenReturn(true)
+
when(stageToMockTaskSetBlacklist(1).isExecutorBlacklistedForTaskSet("executor3"))
+ .thenReturn(true)
+
when(stageToMockTaskSetBlacklist(0).isExecutorBlacklistedForTask("executor0",
0))
+ .thenReturn(true)
+ IndexedSeq(
+ new WorkerOffer("executor0", "host0", 1),
+ new WorkerOffer("executor1", "host1", 1),
+ new WorkerOffer("executor2", "host1", 1),
+ new WorkerOffer("executor3", "host2", 10)
+ )
+ }
+
+ test("scheduled tasks obey task and stage blacklists") {
+ taskScheduler = setupSchedulerWithMockTaskSetBlacklist()
+ val firstTaskAttempts =
taskScheduler.resourceOffers(taskSetBlacklistSetup()).flatten
+ // Whenever we schedule a task, we must consult the node and executor
blacklist. (The test
+ // doesn't check exactly what checks are made the offers get shuffled.)
+ (0 to 2).foreach { stageId =>
+ verify(stageToMockTaskSetBlacklist(stageId), atLeast(1))
+ .isNodeBlacklistedForTaskSet(anyString())
+ verify(stageToMockTaskSetBlacklist(stageId), atLeast(1))
+ .isExecutorBlacklistedForTaskSet(anyString())
+ }
+
+ // When an executor or node is blacklisted, we want to make sure that
we don't try scheduling
+ // each pending task, one by one, to discover they are all
blacklisted. This is important for
+ // performance -- if we did check each task one-by-one, then
responding to a resource offer
+ // (which is usually O(1)-ish) would become O(numPendingTasks), which
would slow down
+ // scheduler throughput and slow down scheduling even on healthy
executors.
+ // Here, we check a proxy for the runtime -- we make sure the
scheduling is short-circuited
+ // at the node or executor blacklist, so we never check the per-task
blacklist.
--- End diff --
ugh, i totally goofed my update here, sorry. Yes, this should be cut here.
But for the equivalent part in the performance test:
We can't just check that `isExecutorBlacklistForTask` is never called,
because it actually should be called for the tasks that are scheduled. (I
think its worthwhile that this test actually schedules tasks on some tasksets,
to avoid any corner cases where nothing is scheduled.) It does need to be
specific for the stage / executor combos.
But you have a good point -- we really need to check that *none* of the
methods are called O(numPendingTasks) times. Eg., we want to make sure that we
don't loop through each task in the taskset, and *inside* the loop check the
node & executor blacklist for the entire taskset.
this will complicate this test (well, the performance one, not this one)
somewhat, but I think its necessary given the issue you're pointing out.
---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at [email protected] or file a JIRA ticket
with INFRA.
---
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]