/**
  * Compute partition sizes in case statistics are available in vertex.
  *
  * @return boolean indicating whether stats are computed
  */
 private synchronized boolean computePartitionSizes() {
   boolean computedPartitionSizes = false;
   for (PendingTaskInfo taskInfo : pendingTasks) {
     int index = taskInfo.index;
     if (targetIndexes != null) { // parallelism has changed.
       Preconditions.checkState(
           index < targetIndexes.length,
           "index=" + index + ", targetIndexes length=" + targetIndexes.length);
       int[] mapping = targetIndexes[index];
       long totalStats = 0;
       for (int i : mapping) {
         totalStats += stats[i];
       }
       if ((totalStats > 0) && (taskInfo.outputStats != totalStats)) {
         computedPartitionSizes = true;
         taskInfo.outputStats = totalStats;
       }
     } else {
       if ((stats[index] > 0) && (stats[index] != taskInfo.outputStats)) {
         computedPartitionSizes = true;
         taskInfo.outputStats = stats[index];
       }
     }
   }
   return computedPartitionSizes;
 }
  private void sortPendingTasksBasedOnDataSize() {
    // Get partition sizes from all source vertices
    boolean statsUpdated = computePartitionSizes();

    if (statsUpdated) {
      // Order the pending tasks based on task size in reverse order
      Collections.sort(
          pendingTasks,
          new Comparator<PendingTaskInfo>() {
            @Override
            public int compare(PendingTaskInfo left, PendingTaskInfo right) {
              return (left.outputStats > right.outputStats)
                  ? -1
                  : ((left.outputStats == right.outputStats) ? 0 : 1);
            }
          });

      if (LOG.isDebugEnabled()) {
        for (PendingTaskInfo pendingTask : pendingTasks) {
          LOG.debug("Pending task:" + pendingTask.toString());
        }
      }
    }
  }