History

sched/eevdf: Speedup short slice task scheduling

When a task with a shorter slice is enqueued, we protect the running task which has a longer slice until it becomes ineligible instead of a full slice in order to speedup the switch to other tasks until the task with the shortest slice is scheduled. This helps to the task to not wait too many full slices before running.

Vincent Guittot committed 4 months ago

Commit 0d1e7a21 parent 7cd2ef11 file · +69 −2Browse files

Showing the changes to kernel (1 of 1 file). Show all

Unified · Split

kernel/sched/fair.c+69−2
@@ -777,6 +777,67 @@ u64 avg_vruntime(struct cfs_rq *cfs_rq) · 776 unmodified lines
777777 return cfs_rq->zero_vruntime;
778778 }
779779
780+/*
781+ * \Sum (v_i - v0)*w_i
782+ * V = ------------------- + v0
783+ * \Sum w_i
784+ *
785+ * Let W = \Sum w_i, and move v_j such that 'v_j == V', thus:
786+ *
787+ * V = 1/W * {(v_j - v0)*w_j + \Sum_i!=j (v_i - v0)*w_i} + v0
788+ *
789+ * v_j = 1/W * {(v_j - v0)*w_j + \Sum_i!=j (v_i - v0)*w_i} + v0
790+ *
791+ * v_j = 1/W * (v_j - v0)*w_j + 1/W * \Sum_i!=j (v_i - v0)*w_i + v0
792+ *
793+ * v_j - 1/W * (v_j - v0)*w_j = 1/W * \Sum_i!=j (v_i - v0)*w_i + v0
794+ *
795+ * v_j*W - (v_j - v0)*w_j = \Sum_i!=j (v_i - v0)*w_i + v0*W
796+ *
797+ * v_j*(W - w_j) + v0*w_j = \Sum_i!=j (v_i - v0)*w_i + v0*W
798+ *
799+ * v_j*(W - w_j) = \Sum_i!=j (v_i - v0)*w_i + v0*(W - w_j)
800+ *
801+ * \Sum_i!=j (v_i - v0)*w_i
802+ * v_j = ------------------------ + v0
803+ * W - w_j
804+ *
805+ * When v_j happens to be curr, then '\Sum_i!=j (v_i - v0)*w_i'
806+ * is cfs_rq->sum_w_runtime, and 'W - w_j' is cfs_rq->sum_weight, since curr
807+ * is not included in the sum.
808+ */
809+static u64 ineligible_vruntime(struct cfs_rq *cfs_rq)
810+{
811+ struct sched_entity *curr = cfs_rq->curr;
812+ long weight = cfs_rq->sum_weight;
813+ s64 delta = 0;
814+
815+ if (curr && !curr->on_rq)
816+ curr = NULL;
817+
818+ /*
819+ * This is called from set_next_task_fair(.first=true) /
820+ * set_protect_slice() so curr had better be set and on_rq.
821+ */
822+ WARN_ON_ONCE(!curr);
823+
824+ if (weight) {
825+ s64 runtime = cfs_rq->sum_w_vruntime;
826+
827+ /*
828+ * Do not add @curr to obtain the effective '- w_j' terms.
829+ */
830+
831+ /* sign flips effective floor / ceiling */
832+ if (runtime < 0)
833+ runtime -= (weight - 1);
834+
835+ delta = div64_long(runtime, weight);
836+ }
837+
838+ return cfs_rq->zero_vruntime + delta + 1;
839+}
840+
780841 static inline u64 cfs_rq_max_slice(struct cfs_rq *cfs_rq);
781842
782843 /*
@@ -1058,8 +1119,14 @@ static inline void set_protect_slice(struct cfs_rq *cfs_rq, struct sched_entity · 275 unmodified lines
10581119 slice = cfs_rq_min_slice(cfs_rq);
10591120
10601121 slice = min(slice, se->slice);
1061− if (slice != se->slice)
1062− vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se));
1122+
1123+ /* If there are shorter slices than se's one */
1124+ if (slice != se->slice) {
1125+ if (sched_feat(PREEMPT_SHORT))
1126+ vprot = min_vruntime(vprot, ineligible_vruntime(cfs_rq));
1127+ else
1128+ vprot = min_vruntime(vprot, se->vruntime + calc_delta_fair(slice, se));
1129+ }
10631130
10641131 se->vprot = vprot;
10651132 }