# HG changeset patch # User Fabian Huch # Date 1701464367 -3600 # Node ID ff68cbfa3550adccc84963b151cf75f6546321d6 # Parent c1255d9870f6f86becc3801618d2495050f7d0a0 clarified path time heuristic: configurable parameters for larger search space; diff -r c1255d9870f6 -r ff68cbfa3550 src/Pure/Tools/build_schedule.scala --- a/src/Pure/Tools/build_schedule.scala Fri Dec 01 21:57:35 2023 +0100 +++ b/src/Pure/Tools/build_schedule.scala Fri Dec 01 21:59:27 2023 +0100 @@ -598,13 +598,36 @@ } } - class Timing_Heuristic( - threshold: Time, + + object Path_Time_Heuristic { + sealed trait Criterion + case class Absolute_Time(time: Time) extends Criterion { + override def toString: String = "absolute time (" + time.message_hms + ")" + } + case class Relative_Time(factor: Double) extends Criterion { + override def toString: String = "relative time (" + factor + ")" + } + + sealed trait Strategy + case class Fixed_Thread(threads: Int) extends Strategy { + override def toString: String = "fixed threads (" + threads + ")" + } + case class Time_Based_Threads(f: Time => Int) extends Strategy { + override def toString: String = "time based threads" + } + } + + class Path_Time_Heuristic( + is_critical: Path_Time_Heuristic.Criterion, + parallel_threads: Path_Time_Heuristic.Strategy, timing_data: Timing_Data, sessions_structure: Sessions.Structure, max_threads_limit: Int = 8 ) extends Path_Heuristic(timing_data, sessions_structure, max_threads_limit) { - override def toString: String = "path time heuristic (threshold: " + threshold.message_hms + ")" + import Path_Time_Heuristic.* + + override def toString: Node = + "path time heuristic (critical: " + is_critical + ", parallel: " + parallel_threads + ")" def next(state: Build_Process.State): List[Config] = { val resources = host_infos.available(state) @@ -625,13 +648,27 @@ resources.try_allocate_tasks(rev_ordered_hosts, all_tasks)._1 } else { - val critical_minimals = state.ready.filter(max_time(_) > threshold).map(_.name) - val critical_nodes = path_max_times(critical_minimals).filter(_._2 > threshold).keySet + def is_critical(time: Time): Boolean = + this.is_critical match { + case Absolute_Time(threshold) => time > threshold + case Relative_Time(factor) => time > minimals.map(max_time).maxBy(_.ms).scale(factor) + } + + val critical_minimals = state.ready.filter(task => is_critical(max_time(task))).map(_.name) + val critical_nodes = + path_max_times(critical_minimals).filter((_, time) => is_critical(time)).keySet val (critical, other) = next_sorted.partition(task => critical_nodes.contains(task.name)) val critical_tasks = critical.map(task => (task, best_threads(task), best_threads(task))) - val other_tasks = other.map(task => (task, 1, best_threads(task))) + + def parallel_threads(task: Build_Process.Task): Int = + this.parallel_threads match { + case Fixed_Thread(threads) => threads + case Time_Based_Threads(f) => f(best_time(task.name)) + } + + val other_tasks = other.map(task => (task, parallel_threads(task), best_threads(task))) val max_critical_parallel = parallel_paths(critical_minimals, critical_nodes.contains) val (critical_hosts, other_hosts) = rev_ordered_hosts.splitAt(max_critical_parallel) @@ -828,9 +865,29 @@ def scheduler(timing_data: Timing_Data, context: Build.Context): Scheduler = { val sessions_structure = context.sessions_structure - val heuristics = - List(5, 10, 20).map(Time.minutes(_)).map( - Timing_Heuristic(_, timing_data, sessions_structure)) + + val is_criticals = + List( + Path_Time_Heuristic.Absolute_Time(Time.minutes(5)), + Path_Time_Heuristic.Absolute_Time(Time.minutes(10)), + Path_Time_Heuristic.Absolute_Time(Time.minutes(20)), + Path_Time_Heuristic.Relative_Time(0.5)) + val parallel_threads = + List( + Path_Time_Heuristic.Fixed_Thread(1), + Path_Time_Heuristic.Time_Based_Threads({ + case time if time < Time.minutes(1) => 1 + case time if time < Time.minutes(5) => 4 + case _ => 8 + })) + + val path_time_heuristics = + for { + is_critical <- is_criticals + parallel <- parallel_threads + } yield Path_Time_Heuristic(is_critical, parallel, timing_data, sessions_structure) + val heuristics = Default_Heuristic(timing_data, context.build_options) :: path_time_heuristics + new Meta_Heuristic(heuristics) }