@Override
    public int compare(TaskWrapper t1, TaskWrapper t2) {
      TaskRunnerCallable o1 = t1.getTaskRunnerCallable();
      TaskRunnerCallable o2 = t2.getTaskRunnerCallable();
      FragmentRuntimeInfo fri1 = o1.getFragmentRuntimeInfo();
      FragmentRuntimeInfo fri2 = o2.getFragmentRuntimeInfo();

      // Regardless of other criteria, ducks are always more important than non-ducks.
      boolean v1 = o1.isGuaranteed(), v2 = o2.isGuaranteed();
      if (v1 != v2) return v1 ? 1 : -1;

      // Then, non-finishable must always precede finishable.
      v1 = o1.canFinishForPriority();
      v2 = o2.canFinishForPriority();
      if (v1 != v2) return v1 ? 1 : -1;

      // Otherwise, heuristics.
      if (fri1.getNumSelfAndUpstreamTasks() > fri2.getNumSelfAndUpstreamTasks()) {
        return 1;
      } else if (fri1.getNumSelfAndUpstreamTasks() < fri2.getNumSelfAndUpstreamTasks()) {
        return -1;
      }
      return 0;
    }
Victim Task (A) should be preempted in favor of a candidate Task (B) when:
   1. A is NOT on the same Vertex as B AND
     1.1. B is a Guaranteed Task while A is not OR
     1.2. Both are guaranteed but A is not finishable and B is
To make sure that Victim task is not behind some upstream updates (asynchronous),
we check its sources' state (by QueryFragmentInfo.canFinish method)
@param candidate Task
@param victim Task
@return True when victim should be preempted in favor of candidate Task
llap-server/src/java/org/apache/hadoop/hive/llap/daemon/impl/TaskExecutorService.java