| author | wenzelm | 
| Thu, 24 Oct 2024 22:05:57 +0200 | |
| changeset 81253 | bbed9f218158 | 
| parent 80480 | 972f7a4cdc0e | 
| child 81340 | 30f7eb65d679 | 
| permissions | -rw-r--r-- | 
| 79502 | 1 | /* Title: Pure/Build/build_schedule.scala | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 2 | Author: Fabian Huch, TU Muenchen | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 3 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 4 | Build schedule generated by Heuristic methods, allowing for more efficient builds. | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 5 | */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 6 | package isabelle | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 7 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 8 | |
| 78846 | 9 | import Host.Node_Info | 
| 79911 | 10 | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 11 | import scala.annotation.tailrec | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 12 | import scala.collection.mutable | 
| 79910 
fbfa7d25749a
tie-breaking in schedule optimization to pick best schedule even when run-time is dominated by large task (e.g., session with long timeout but no data yet);
 Fabian Huch <huch@in.tum.de> parents: 
79909diff
changeset | 13 | import scala.Ordering.Implicits.seqOrdering | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 14 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 15 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 16 | object Build_Schedule {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 17 | /* organized historic timing information (extracted from build logs) */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 18 | |
| 79593 | 19 |   case class Result(job_name: String, hostname: String, threads: Int, timing: Timing) {
 | 
| 79085 
cf51ccfd3e39
use full timing information in build schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79084diff
changeset | 20 | def elapsed: Time = timing.elapsed | 
| 79087 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 21 | def proper_cpu: Option[Time] = timing.cpu.proper_ms.map(Time.ms) | 
| 79085 
cf51ccfd3e39
use full timing information in build schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79084diff
changeset | 22 | } | 
| 79189 | 23 | |
| 24 |   object Timing_Data {
 | |
| 25 | def median_timing(obs: List[Timing]): Timing = obs.sortBy(_.elapsed.ms).apply(obs.length / 2) | |
| 26 | ||
| 27 | def median_time(obs: List[Time]): Time = obs.sortBy(_.ms).apply(obs.length / 2) | |
| 28 | ||
| 29 | def mean_time(obs: Iterable[Time]): Time = Time.ms(obs.map(_.ms).sum / obs.size) | |
| 30 | ||
| 31 |     private def dummy_entries(host: Host, host_factor: Double) = {
 | |
| 32 | val baseline = Time.minutes(5).scale(host_factor) | |
| 33 | val gc = Time.seconds(10).scale(host_factor) | |
| 34 | List( | |
| 79593 | 35 |         Result("dummy", host.name, 1, Timing(baseline, baseline, gc)),
 | 
| 36 |         Result("dummy", host.name, 8, Timing(baseline.scale(0.2), baseline, gc)))
 | |
| 79189 | 37 | } | 
| 38 | ||
| 39 | def make( | |
| 40 | host_infos: Host_Infos, | |
| 41 | build_history: List[(Build_Log.Meta_Info, Build_Log.Build_Info)], | |
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 42 | session_structure: Sessions.Structure, | 
| 79189 | 43 |     ): Timing_Data = {
 | 
| 44 | val hosts = host_infos.hosts | |
| 45 | val measurements = | |
| 46 |         for {
 | |
| 47 | (meta_info, build_info) <- build_history | |
| 79818 
0c2a62a9f136
more operations for Build_Log.Meta_Info: prefer explicit types;
 wenzelm parents: 
79805diff
changeset | 48 | build_host = meta_info.get_build_host | 
| 79189 | 49 | (job_name, session_info) <- build_info.sessions.toList | 
| 50 | if build_info.finished_sessions.contains(job_name) | |
| 51 | hostname <- session_info.hostname.orElse(build_host).toList | |
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 52 | host <- hosts.find(_.name == hostname).toList | 
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 53 | threads = session_info.threads.getOrElse(host.max_threads) | 
| 79189 | 54 | } yield (job_name, hostname, threads) -> session_info.timing | 
| 55 | ||
| 56 | val entries = | |
| 57 |         if (measurements.isEmpty) {
 | |
| 58 | val default_host = host_infos.hosts.sorted(host_infos.host_speeds).last | |
| 59 | host_infos.hosts.flatMap(host => | |
| 60 | dummy_entries(host, host_infos.host_factor(default_host, host))) | |
| 61 | } | |
| 62 | else | |
| 63 |           measurements.groupMap(_._1)(_._2).toList.map {
 | |
| 64 | case ((job_name, hostname, threads), timings) => | |
| 79593 | 65 | Result(job_name, hostname, threads, median_timing(timings)) | 
| 79189 | 66 | } | 
| 67 | ||
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 68 | new Timing_Data(new Facet(entries), host_infos, session_structure) | 
| 79189 | 69 | } | 
| 70 | ||
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 71 | def load( | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 72 | host_infos: Host_Infos, | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 73 | log_database: SQL.Database, | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 74 | sessions_structure: Sessions.Structure | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 75 |     ): Timing_Data = {
 | 
| 79189 | 76 | val build_history = | 
| 77 |         for {
 | |
| 78 | log_name <- log_database.execute_query_statement( | |
| 79 | Build_Log.private_data.meta_info_table.select(List(Build_Log.Column.log_name)), | |
| 80 | List.from[String], res => res.string(Build_Log.Column.log_name)) | |
| 81 | meta_info <- Build_Log.private_data.read_meta_info(log_database, log_name) | |
| 82 | build_info = Build_Log.private_data.read_build_info(log_database, log_name) | |
| 83 | } yield (meta_info, build_info) | |
| 84 | ||
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 85 | make(host_infos, build_history, sessions_structure) | 
| 79189 | 86 | } | 
| 79593 | 87 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 88 |     def restrict(full_data: Timing_Data, host_infos: Host_Infos): Timing_Data = {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 89 | val hostnames = host_infos.hosts.map(_.name).toSet | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 90 | val results = full_data.facet.results.filter(result => hostnames.contains(result.hostname)) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 91 | new Timing_Data(new Facet(results), host_infos, full_data.sessions_structure) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 92 | } | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 93 | |
| 79593 | 94 | |
| 95 | /* data facets */ | |
| 96 | ||
| 97 |     object Facet {
 | |
| 98 | def unapply(facet: Facet): Option[List[Result]] = Some(facet.results) | |
| 99 | } | |
| 100 | ||
| 101 |     class Facet private[Timing_Data](val results: List[Result]) {
 | |
| 102 | require(results.nonEmpty) | |
| 103 | ||
| 79649 
981cd49a3f90
more explicit types --- fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79648diff
changeset | 104 | def is_empty: Boolean = results.isEmpty | 
| 79593 | 105 | |
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 106 | def size: Int = results.length | 
| 79593 | 107 | |
| 79649 
981cd49a3f90
more explicit types --- fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79648diff
changeset | 108 | lazy val by_job: Map[String, Facet] = results.groupBy(_.job_name).view.mapValues(new Facet(_)).toMap | 
| 
981cd49a3f90
more explicit types --- fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79648diff
changeset | 109 | lazy val by_threads: Map[Int, Facet] = results.groupBy(_.threads).view.mapValues(new Facet(_)).toMap | 
| 
981cd49a3f90
more explicit types --- fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79648diff
changeset | 110 | lazy val by_hostname: Map[String, Facet] = results.groupBy(_.hostname).view.mapValues(new Facet(_)).toMap | 
| 79593 | 111 | |
| 79913 | 112 | def median_time: Time = Timing_Data.median_time(results.map(_.elapsed)) | 
| 79593 | 113 | |
| 114 | def best_result: Result = results.minBy(_.elapsed.ms) | |
| 115 | } | |
| 79189 | 116 | } | 
| 117 | ||
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 118 | class Timing_Data private( | 
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 119 | private val facet: Timing_Data.Facet, | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 120 | val host_infos: Host_Infos, | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 121 | val sessions_structure: Sessions.Structure | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 122 |   ) {
 | 
| 79025 
f78ee2d48bf5
handle inflection point in interpolation with monotone prefix;
 Fabian Huch <huch@in.tum.de> parents: 
79024diff
changeset | 123 | private def inflection_point(last_mono: Int, next: Int): Int = | 
| 
f78ee2d48bf5
handle inflection point in interpolation with monotone prefix;
 Fabian Huch <huch@in.tum.de> parents: 
79024diff
changeset | 124 | last_mono + ((next - last_mono) / 2) | 
| 
f78ee2d48bf5
handle inflection point in interpolation with monotone prefix;
 Fabian Huch <huch@in.tum.de> parents: 
79024diff
changeset | 125 | |
| 79028 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 126 |     def best_threads(job_name: String, max_threads: Int): Int = {
 | 
| 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 127 | val worse_threads = | 
| 79593 | 128 |         facet.by_job.get(job_name).toList.flatMap(_.by_hostname).flatMap {
 | 
| 129 | case (hostname, facet) => | |
| 130 | val best_threads = facet.best_result.threads | |
| 79911 | 131 | facet.by_threads.keys.toList.sorted.find(_ > best_threads).map( | 
| 79028 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 132 | inflection_point(best_threads, _)) | 
| 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 133 | } | 
| 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 134 | (max_threads :: worse_threads).min | 
| 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 135 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 136 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 137 | private def hostname_factor(from: String, to: String): Double = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 138 | host_infos.host_factor(host_infos.the_host(from), host_infos.the_host(to)) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 139 | |
| 79041 | 140 |     private def approximate_threads(entries_unsorted: List[(Int, Time)], threads: Int): Time = {
 | 
| 141 | val entries = entries_unsorted.sortBy(_._1) | |
| 142 | ||
| 79036 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 143 | def sorted_prefix[A](xs: List[A], f: A => Long): List[A] = | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 144 |         xs match {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 145 | case x1 :: x2 :: xs => | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 146 | if (f(x1) <= f(x2)) x1 :: sorted_prefix(x2 :: xs, f) else x1 :: Nil | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 147 | case xs => xs | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 148 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 149 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 150 |       def linear(p0: (Int, Time), p1: (Int, Time)): Time = {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 151 | val a = (p1._2 - p0._2).scale(1.0 / (p1._1 - p0._1)) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 152 | val b = p0._2 - a.scale(p0._1) | 
| 79184 | 153 | (a.scale(threads) + b) max Time.zero | 
| 79036 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 154 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 155 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 156 | val mono_prefix = sorted_prefix(entries, e => -e._2.ms) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 157 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 158 | val is_mono = entries == mono_prefix | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 159 | val in_prefix = mono_prefix.length > 1 && threads <= mono_prefix.last._1 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 160 | val in_inflection = | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 161 | !is_mono && mono_prefix.length > 1 && threads < entries.drop(mono_prefix.length).head._1 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 162 |       if (is_mono || in_prefix || in_inflection) {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 163 | // Model with Amdahl's law | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 164 | val t_p = | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 165 |           Timing_Data.median_time(for {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 166 | (n, t0) <- mono_prefix | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 167 | (m, t1) <- mono_prefix | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 168 | if m != n | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 169 | } yield (t0 - t1).scale(n.toDouble * m / (m - n))) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 170 | val t_c = | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 171 | Timing_Data.median_time(for ((n, t) <- mono_prefix) yield t - t_p.scale(1.0 / n)) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 172 | |
| 79184 | 173 | def model(threads: Int): Time = (t_c + t_p.scale(1.0 / threads)) max Time.zero | 
| 79036 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 174 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 175 | if (is_mono || in_prefix) model(threads) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 176 |         else {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 177 | val post_inflection = entries.drop(mono_prefix.length).head | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 178 | val inflection_threads = inflection_point(mono_prefix.last._1, post_inflection._1) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 179 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 180 | if (threads <= inflection_threads) model(threads) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 181 | else linear((inflection_threads, model(inflection_threads)), post_inflection) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 182 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 183 |       } else {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 184 | // Piecewise linear | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 185 | val (p0, p1) = | 
| 79042 | 186 |           if (entries.head._1 < threads && threads < entries.last._1) {
 | 
| 187 | val split = entries.partition(_._1 < threads) | |
| 79036 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 188 | (split._1.last, split._2.head) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 189 |           } else {
 | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 190 | val piece = if (threads < entries.head._1) entries.take(2) else entries.takeRight(2) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 191 | (piece.head, piece.last) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 192 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 193 | |
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 194 | linear(p0, p1) | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 195 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 196 | } | 
| 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 197 | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 198 |     private def unify_hosts(job_name: String, on_host: String): List[(Int, Time)] = {
 | 
| 79593 | 199 | def unify(hostname: String, facet: Timing_Data.Facet) = | 
| 79913 | 200 | facet.median_time.scale(hostname_factor(hostname, on_host)) | 
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 201 | |
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 202 |       for {
 | 
| 79593 | 203 | facet <- facet.by_job.get(job_name).toList | 
| 204 | (threads, facet) <- facet.by_threads | |
| 205 | entries = facet.by_hostname.toList.map(unify) | |
| 79913 | 206 | } yield threads -> Timing_Data.mean_time(entries) | 
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 207 | } | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 208 | |
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 209 |     def estimate_threads(job_name: String, hostname: String, threads: Int): Option[Time] = {
 | 
| 79593 | 210 |       def try_approximate(facet: Timing_Data.Facet): Option[Time] = {
 | 
| 79087 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 211 | val entries = | 
| 79593 | 212 |           facet.by_threads.toList match {
 | 
| 213 | case List((i, Timing_Data.Facet(List(result)))) if i != 1 => | |
| 79913 | 214 | (i, facet.median_time) :: result.proper_cpu.map(1 -> _).toList | 
| 215 | case entries => entries.map((threads, facet) => threads -> facet.median_time) | |
| 79087 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 216 | } | 
| 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 217 | if (entries.size < 2) None else Some(approximate_threads(entries, threads)) | 
| 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 218 | } | 
| 
3620010c410a
use cpu time for approximation;
 Fabian Huch <huch@in.tum.de> parents: 
79086diff
changeset | 219 | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 220 |       for {
 | 
| 79593 | 221 | facet <- facet.by_job.get(job_name) | 
| 222 | facet <- facet.by_hostname.get(hostname) | |
| 79913 | 223 | time <- facet.by_threads.get(threads).map(_.median_time).orElse(try_approximate(facet)) | 
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 224 | } yield time | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 225 | } | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 226 | |
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 227 |     def global_threads_factor(from: Int, to: Int): Double = {
 | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 228 | def median(xs: Iterable[Double]): Double = xs.toList.sorted.apply(xs.size / 2) | 
| 79036 
be42ba4b4672
split actual approximation from data handling;
 Fabian Huch <huch@in.tum.de> parents: 
79035diff
changeset | 229 | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 230 | val estimates = | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 231 |         for {
 | 
| 79593 | 232 | (hostname, facet) <- facet.by_hostname | 
| 233 | job_name <- facet.by_job.keys | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 234 | from_time <- estimate_threads(job_name, hostname, from) | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 235 | to_time <- estimate_threads(job_name, hostname, to) | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 236 | } yield from_time.ms.toDouble / to_time.ms | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 237 | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 238 | if (estimates.nonEmpty) median(estimates) | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 239 |       else {
 | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 240 | // unify hosts | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 241 | val estimates = | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 242 |           for {
 | 
| 79593 | 243 | (job_name, facet) <- facet.by_job | 
| 244 | hostname = facet.by_hostname.keys.head | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 245 | entries = unify_hosts(job_name, hostname) | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 246 | if entries.length > 1 | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 247 | } yield | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 248 | approximate_threads(entries, from).ms.toDouble / approximate_threads(entries, to).ms | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 249 | |
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 250 | if (estimates.nonEmpty) median(estimates) | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 251 | else from.toDouble / to.toDouble | 
| 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 252 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 253 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 254 | |
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 255 | private var cache: Map[(String, String, Int), Time] = Map.empty | 
| 79911 | 256 | |
| 257 | ||
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 258 | /* approximation factors -- penalize estimations with less information */ | 
| 79911 | 259 | |
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 260 | val FACTOR_NO_THREADS_GLOBAL_CURVE = 2.5 | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 261 | val FACTOR_NO_THREADS_UNIFY_MACHINES = 1.7 | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 262 | val FACTOR_NO_THREADS_OTHER_MACHINE = 1.5 | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 263 | val FACTOR_NO_THREADS_SAME_MACHINE = 1.4 | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 264 | val FACTOR_THREADS_OTHER_MACHINE = 1.2 | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 265 | |
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 266 |     def estimate(job_name: String, hostname: String, threads: Int): Time = {
 | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 267 | def estimate: Time = | 
| 79593 | 268 |         facet.by_job.get(job_name) match {
 | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 269 | case None => | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 270 | // no data for job, use timeout as esimation for single-threaded job on worst host | 
| 79895 
4ec26ed6f481
proper check (amending 9aef1d1535ff);
 Fabian Huch <huch@in.tum.de> parents: 
79892diff
changeset | 271 | val default_time = sessions_structure.get(job_name).map(_.timeout).getOrElse(Time.zero) | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 272 |             if (default_time > Time.zero) {
 | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 273 | val default_host = host_infos.hosts.sorted(host_infos.host_speeds).head | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 274 | default_time | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 275 | .scale(global_threads_factor(1, threads)) | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 276 | .scale(hostname_factor(default_host.name, hostname)) | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 277 | } | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 278 |             else {
 | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 279 | // no timeout, take average of other jobs for given threads | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 280 | val job_estimates = facet.by_job.keys.flatMap(estimate_threads(_, hostname, threads)) | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 281 | if (job_estimates.nonEmpty) Timing_Data.mean_time(job_estimates) | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 282 |               else {
 | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 283 | // no other job to estimate from, use global curve to approximate any other job | 
| 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 284 | val (threads1, facet1) = facet.by_threads.head | 
| 79913 | 285 | facet1.median_time.scale(global_threads_factor(threads1, threads)) | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 286 | } | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 287 | } | 
| 79038 
cd7c1acc9cf2
better estimation for unknown jobs;
 Fabian Huch <huch@in.tum.de> parents: 
79037diff
changeset | 288 | |
| 79593 | 289 | case Some(facet) => | 
| 290 |             facet.by_threads.get(threads) match {
 | |
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 291 | case None => // interpolate threads | 
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 292 | estimate_threads(job_name, hostname, threads).map(_.scale( | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 293 |                   FACTOR_NO_THREADS_SAME_MACHINE)).getOrElse {
 | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 294 | // per machine, try to approximate config for threads | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 295 | val approximated = | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 296 |                     for {
 | 
| 79593 | 297 | hostname1 <- facet.by_hostname.keys | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 298 | estimate <- estimate_threads(job_name, hostname1, threads) | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 299 | factor = hostname_factor(hostname1, hostname) | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 300 | } yield estimate.scale(factor) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 301 | |
| 79911 | 302 | if (approximated.nonEmpty) | 
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 303 | Timing_Data.mean_time(approximated).scale(FACTOR_NO_THREADS_OTHER_MACHINE) | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 304 |                   else {
 | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 305 | // no single machine where config can be approximated, unify data points | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 306 | val unified_entries = unify_hosts(job_name, hostname) | 
| 79037 
1b3a6cc4a2bf
clarified and tuned timing estimation;
 Fabian Huch <huch@in.tum.de> parents: 
79036diff
changeset | 307 | |
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 308 | if (unified_entries.length > 1) | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 309 | approximate_threads(unified_entries, threads).scale( | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 310 | FACTOR_NO_THREADS_UNIFY_MACHINES) | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 311 |                     else {
 | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 312 | // only single data point, use global curve to approximate | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 313 | val (job_threads, job_time) = unified_entries.head | 
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 314 | job_time.scale(global_threads_factor(job_threads, threads)).scale( | 
| 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 315 | FACTOR_NO_THREADS_GLOBAL_CURVE) | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 316 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 317 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 318 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 319 | |
| 79593 | 320 | case Some(facet) => // time for job/thread exists, interpolate machine if necessary | 
| 79913 | 321 |                 facet.by_hostname.get(hostname).map(_.median_time).getOrElse {
 | 
| 322 | Timing_Data.mean_time( | |
| 79593 | 323 | facet.by_hostname.toList.map((hostname1, facet) => | 
| 79913 | 324 | facet.median_time.scale(hostname_factor(hostname1, hostname)))).scale( | 
| 79534 
1dcc97227442
add approximation factors in build schedule to estimate build times more conservatively;
 Fabian Huch <huch@in.tum.de> parents: 
79527diff
changeset | 325 | FACTOR_THREADS_OTHER_MACHINE) | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 326 | } | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 327 | } | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 328 | } | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 329 | |
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 330 |       cache.get(job_name, hostname, threads) match {
 | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 331 | case Some(time) => time | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 332 | case None => | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 333 | val time = estimate | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 334 | cache = cache + ((job_name, hostname, threads) -> time) | 
| 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 335 | time | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 336 | } | 
| 79178 
96e5d12c82fd
performance tuning: cache estimates;
 Fabian Huch <huch@in.tum.de> parents: 
79110diff
changeset | 337 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 338 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 339 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 340 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 341 | /* host information */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 342 | |
| 79925 | 343 |   object Host {
 | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 344 |     def load(options: Options, build_host: Build_Cluster.Host, host_db: SQL.Database): Host = {
 | 
| 79925 | 345 | val name = build_host.name | 
| 346 | val info = | |
| 347 |         isabelle.Host.read_info(host_db, name).getOrElse(error("No info for host " + quote(name)))
 | |
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 348 | val max_threads = (options ++ build_host.options).threads(default = info.num_cpus) | 
| 79925 | 349 |       val score = info.benchmark_score.getOrElse(error("No benchmark for " + quote(name)))
 | 
| 350 | ||
| 351 | Host( | |
| 352 | name = name, | |
| 353 | num_cpus = info.num_cpus, | |
| 354 | max_jobs = build_host.jobs, | |
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 355 | max_threads = max_threads, | 
| 79925 | 356 | numa = build_host.numa, | 
| 357 | numa_nodes = info.numa_nodes, | |
| 358 | benchmark_score = score, | |
| 359 | options = build_host.options) | |
| 360 | } | |
| 361 | } | |
| 362 | ||
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 363 | case class Host( | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 364 | name: String, | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 365 | num_cpus: Int, | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 366 | max_jobs: Int, | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 367 | max_threads: Int, | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 368 | benchmark_score: Double, | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 369 | numa: Boolean = false, | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 370 | numa_nodes: List[Int] = Nil, | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 371 | options: List[Options.Spec] = Nil) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 372 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 373 |   object Host_Infos {
 | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 374 | def load( | 
| 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 375 | options: Options, | 
| 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 376 | build_hosts: List[Build_Cluster.Host], | 
| 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 377 | host_db: SQL.Database | 
| 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 378 | ): Host_Infos = new Host_Infos(build_hosts.map(Host.load(options, _, host_db))) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 379 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 380 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 381 |   case class Host_Infos(hosts: List[Host]) {
 | 
| 79040 | 382 | require(hosts.nonEmpty) | 
| 383 | ||
| 79103 
883f61f0beda
clarified build schedule host: more operations;
 Fabian Huch <huch@in.tum.de> parents: 
79102diff
changeset | 384 | private val by_hostname = hosts.map(host => host.name -> host).toMap | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 385 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 386 | def host_factor(from: Host, to: Host): Double = | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 387 | from.benchmark_score / to.benchmark_score | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 388 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 389 | val host_speeds: Ordering[Host] = | 
| 79084 | 390 | Ordering.fromLessThan((host1, host2) => host_factor(host1, host2) < 1) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 391 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 392 | def the_host(hostname: String): Host = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 393 |       by_hostname.getOrElse(hostname, error("Unknown host " + quote(hostname)))
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 394 | def the_host(node_info: Node_Info): Host = the_host(node_info.hostname) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 395 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 396 | def num_threads(node_info: Node_Info): Int = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 397 | if (node_info.rel_cpus.nonEmpty) node_info.rel_cpus.length | 
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 398 | else the_host(node_info).max_threads | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 399 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 400 |     def available(state: Build_Process.State): Resources = {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 401 | val allocated = | 
| 79594 | 402 | state.running.values.map(_.node_info).groupMapReduce(_.hostname)(List(_))(_ ::: _) | 
| 403 | new Resources(this, allocated) | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 404 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 405 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 406 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 407 | |
| 79029 | 408 | /* offline tracking of job configurations and resource allocations */ | 
| 409 | ||
| 410 |   case class Config(job_name: String, node_info: Node_Info) {
 | |
| 411 | def job_of(start_time: Time): Build_Process.Job = | |
| 412 | Build_Process.Job(job_name, "", "", node_info, Date(start_time), None) | |
| 413 | } | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 414 | |
| 79594 | 415 | class Resources( | 
| 416 | val host_infos: Host_Infos, | |
| 417 | allocated_nodes: Map[String, List[Node_Info]] | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 418 |   ) {
 | 
| 79106 | 419 | def unused_nodes(host: Host, threads: Int): List[Node_Info] = | 
| 420 | if (!available(host, threads)) Nil | |
| 421 |       else {
 | |
| 422 | val node = next_node(host, threads) | |
| 423 | node :: allocate(node).unused_nodes(host, threads) | |
| 424 | } | |
| 425 | ||
| 426 | def unused_nodes(threads: Int): List[Node_Info] = | |
| 427 | host_infos.hosts.flatMap(unused_nodes(_, threads)) | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 428 | |
| 79594 | 429 | def allocated(host: Host): List[Node_Info] = allocated_nodes.getOrElse(host.name, Nil) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 430 | |
| 79593 | 431 |     def allocate(node_info: Node_Info): Resources = {
 | 
| 432 | val host = host_infos.the_host(node_info) | |
| 79594 | 433 | new Resources(host_infos, allocated_nodes + (host.name -> (node_info :: allocated(host)))) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 434 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 435 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 436 | def try_allocate_tasks( | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 437 | hosts: List[(Host, Int)], | 
| 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 438 | tasks: List[(Build_Process.Task, Int, Int)], | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 439 | ): (List[Config], Resources) = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 440 |       tasks match {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 441 | case Nil => (Nil, this) | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 442 | case (task, min_threads, max_threads) :: tasks => | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 443 | val (config, resources) = | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 444 |             hosts.find((host, _) => available(host, min_threads)) match {
 | 
| 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 445 | case Some((host, host_max_threads)) => | 
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 446 | val free_threads = host.max_threads - ((host.max_jobs - 1) * host_max_threads) | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 447 | val node_info = next_node(host, (min_threads max free_threads) min max_threads) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 448 | (Some(Config(task.name, node_info)), allocate(node_info)) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 449 | case None => (None, this) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 450 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 451 | val (configs, resources1) = resources.try_allocate_tasks(hosts, tasks) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 452 | (configs ++ config, resources1) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 453 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 454 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 455 |     def next_node(host: Host, threads: Int): Node_Info = {
 | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 456 | val numa_node_num_cpus = host.num_cpus / (host.numa_nodes.length max 1) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 457 | def explicit_cpus(node_info: Node_Info): List[Int] = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 458 | if (node_info.rel_cpus.nonEmpty) node_info.rel_cpus else (0 until numa_node_num_cpus).toList | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 459 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 460 | val used_nodes = allocated(host).groupMapReduce(_.numa_node)(explicit_cpus)(_ ::: _) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 461 | |
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 462 | val available_nodes = host.numa_nodes | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 463 | val numa_node = | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 464 | if (!host.numa) None | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 465 | else available_nodes.sortBy(n => used_nodes.getOrElse(Some(n), Nil).length).headOption | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 466 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 467 | val used_cpus = used_nodes.getOrElse(numa_node, Nil).toSet | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 468 | val available_cpus = (0 until numa_node_num_cpus).filterNot(used_cpus.contains).toList | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 469 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 470 | val rel_cpus = if (available_cpus.length >= threads) available_cpus.take(threads) else Nil | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 471 | |
| 79103 
883f61f0beda
clarified build schedule host: more operations;
 Fabian Huch <huch@in.tum.de> parents: 
79102diff
changeset | 472 | Node_Info(host.name, numa_node, rel_cpus) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 473 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 474 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 475 |     def available(host: Host, threads: Int): Boolean = {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 476 | val used = allocated(host) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 477 | |
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 478 | if (used.length >= host.max_jobs) false | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 479 |       else {
 | 
| 80109 
dbcd6dc7f70f
back to static numa_nodes (reverting part of c2c59de57df9);
 wenzelm parents: 
80056diff
changeset | 480 |         if (host.numa_nodes.length <= 1) {
 | 
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 481 | used.map(host_infos.num_threads).sum + threads <= host.max_threads | 
| 80109 
dbcd6dc7f70f
back to static numa_nodes (reverting part of c2c59de57df9);
 wenzelm parents: 
80056diff
changeset | 482 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 483 |         else {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 484 | def node_threads(n: Int): Int = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 485 | used.filter(_.numa_node.contains(n)).map(host_infos.num_threads).sum | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 486 | |
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 487 | host.numa_nodes.exists( | 
| 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 488 | node_threads(_) + threads <= host.num_cpus / host.numa_nodes.length) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 489 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 490 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 491 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 492 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 493 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 494 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 495 | /* schedule generation */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 496 | |
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 497 |   object Schedule {
 | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 498 |     case class Node(job_name: String, node_info: Node_Info, start: Date, duration: Time) {
 | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 499 | def end: Date = Date(start.time + duration) | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 500 | } | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 501 | |
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 502 | type Graph = isabelle.Graph[String, Node] | 
| 79183 
32d00ec387f4
use schedule directly instead of extra cache;
 Fabian Huch <huch@in.tum.de> parents: 
79182diff
changeset | 503 | |
| 79185 | 504 | def init(build_uuid: String): Schedule = Schedule(build_uuid, "none", Date.now(), Graph.empty) | 
| 79914 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 505 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 506 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 507 | /* file representation */ | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 508 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 509 |     def write(value: Schedule, file: Path): Unit = {
 | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 510 | import XML.Encode._ | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 511 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 512 | def time: T[Time] = (time => long(time.ms)) | 
| 79916 
cfeb3a8f241d
read/write proper schedule date (amending 9da3019e1ee5);
 Fabian Huch <huch@in.tum.de> parents: 
79915diff
changeset | 513 | def date: T[Date] = (date => time(date.time)) | 
| 79914 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 514 | def node_info: T[Node_Info] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 515 | (node_info => triple(string, option(int), list(int))( | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 516 | (node_info.hostname, node_info.numa_node, node_info.rel_cpus))) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 517 | def node: T[Node] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 518 | (node => pair(string, pair(node_info, pair(date, time)))( | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 519 | (node.job_name, (node.node_info, (node.start, node.duration))))) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 520 | def schedule: T[Schedule] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 521 | (schedule => | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 522 | pair(string, pair(string, pair(date, pair(Graph.encode(string, node), long))))(( | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 523 | schedule.build_uuid, (schedule.generator, (schedule.start, (schedule.graph, | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 524 | schedule.serial)))))) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 525 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 526 | File.write(file, YXML.string_of_body(schedule(value))) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 527 | } | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 528 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 529 |     def read(file: Path): Schedule = {
 | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 530 | import XML.Decode._ | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 531 | |
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 532 |       def time: T[Time] = { body => Time.ms(long(body)) }
 | 
| 79916 
cfeb3a8f241d
read/write proper schedule date (amending 9da3019e1ee5);
 Fabian Huch <huch@in.tum.de> parents: 
79915diff
changeset | 533 |       def date: T[Date] = { body => Date(time(body)) }
 | 
| 79914 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 534 | def node_info: T[Node_Info] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 535 |         { body =>
 | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 536 | val (hostname, numa_node, rel_cpus) = triple(string, option(int), list(int))(body) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 537 | Node_Info(hostname, numa_node, rel_cpus) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 538 | } | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 539 | val node: T[Schedule.Node] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 540 |         { body =>
 | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 541 | val (job_name, (info, (start, duration))) = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 542 | pair(string, pair(node_info, pair(date, time)))(body) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 543 | Node(job_name, info, start, duration) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 544 | } | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 545 | def schedule: T[Schedule] = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 546 |         { body =>
 | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 547 | val (build_uuid, (generator, (start, (graph, serial)))) = | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 548 | pair(string, pair(string, (pair(date, pair(Graph.decode(string, node), long)))))(body) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 549 | Schedule(build_uuid, generator, start, graph, serial) | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 550 | } | 
| 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 551 | |
| 80480 
972f7a4cdc0e
clarified YXML.Source: more direct support for String and Bytes, instead of CharSequence;
 wenzelm parents: 
80476diff
changeset | 552 | schedule(YXML.parse_body(Bytes.read(file))) | 
| 79914 
9da3019e1ee5
file representation for schedule (e.g., for generating from external tool);
 Fabian Huch <huch@in.tum.de> parents: 
79913diff
changeset | 553 | } | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 554 | } | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 555 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 556 | case class Schedule( | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 557 | build_uuid: String, | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 558 | generator: String, | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 559 | start: Date, | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 560 | graph: Schedule.Graph, | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 561 | serial: Long = 0, | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 562 |   ) {
 | 
| 79835 | 563 | def next_serial: Long = Build_Process.State.inc_serial(serial) | 
| 564 | ||
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 565 | def end: Date = | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 566 | if (graph.is_empty) start | 
| 79897 | 567 | else graph.maximals.map(graph.get_node).map(_.end).max(Date.Ordering) | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 568 | |
| 79819 | 569 | def duration: Time = end - start | 
| 79910 
fbfa7d25749a
tie-breaking in schedule optimization to pick best schedule even when run-time is dominated by large task (e.g., session with long timeout but no data yet);
 Fabian Huch <huch@in.tum.de> parents: 
79909diff
changeset | 570 | def durations: List[Time] = graph.keys.map(graph.get_node(_).end - start) | 
| 79109 
c1255d9870f6
clarified heuristics toString;
 Fabian Huch <huch@in.tum.de> parents: 
79108diff
changeset | 571 | def message: String = "Estimated " + duration.message_hms + " build time with " + generator | 
| 79183 
32d00ec387f4
use schedule directly instead of extra cache;
 Fabian Huch <huch@in.tum.de> parents: 
79182diff
changeset | 572 | |
| 79819 | 573 | def deviation(other: Schedule): Time = Time.ms((end - other.end).ms.abs) | 
| 79192 
5db03f9276e2
clarified: build schedules may be outdated when empty, after some time, or due to build progress;
 Fabian Huch <huch@in.tum.de> parents: 
79191diff
changeset | 574 | |
| 
5db03f9276e2
clarified: build schedules may be outdated when empty, after some time, or due to build progress;
 Fabian Huch <huch@in.tum.de> parents: 
79191diff
changeset | 575 | def num_built(state: Build_Process.State): Int = graph.keys.count(state.results.contains) | 
| 
5db03f9276e2
clarified: build schedules may be outdated when empty, after some time, or due to build progress;
 Fabian Huch <huch@in.tum.de> parents: 
79191diff
changeset | 576 | def elapsed(): Time = Time.now() - start.time | 
| 79293 | 577 | def is_empty: Boolean = graph.is_empty | 
| 79289 
7c1faa16554b
add delay and limit options for when schedule is considered outdated;
 Fabian Huch <huch@in.tum.de> parents: 
79288diff
changeset | 578 | def is_outdated(options: Options, state: Build_Process.State): Boolean = | 
| 79293 | 579 | if (is_empty) true | 
| 79912 
fe96a842f065
remove schedule outdated limit: delay is sufficient;
 Fabian Huch <huch@in.tum.de> parents: 
79911diff
changeset | 580 |       else elapsed() > options.seconds("build_schedule_outdated_delay")
 | 
| 79183 
32d00ec387f4
use schedule directly instead of extra cache;
 Fabian Huch <huch@in.tum.de> parents: 
79182diff
changeset | 581 | |
| 79921 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 582 |     def next(hostname: String, state: Build_Process.State): List[String] = {
 | 
| 79946 
05e034a54924
only start jobs early if they are due (cf. 1966578feff8);
 Fabian Huch <huch@in.tum.de> parents: 
79935diff
changeset | 583 | val now = Time.now() | 
| 
05e034a54924
only start jobs early if they are due (cf. 1966578feff8);
 Fabian Huch <huch@in.tum.de> parents: 
79935diff
changeset | 584 | |
| 79921 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 585 | val next_nodes = | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 586 |         for {
 | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 587 | task <- state.next_ready | 
| 79931 
f08e5a234c1b
always check if node is defined, e.g. for exists_next operation wit empty schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79928diff
changeset | 588 | if graph.defined(task.name) | 
| 79921 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 589 | node = graph.get_node(task.name) | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 590 | if hostname == node.node_info.hostname | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 591 | } yield node | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 592 | |
| 79946 
05e034a54924
only start jobs early if they are due (cf. 1966578feff8);
 Fabian Huch <huch@in.tum.de> parents: 
79935diff
changeset | 593 | val (ready, other) = | 
| 79921 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 594 | next_nodes.partition(node => graph.imm_preds(node.job_name).subsetOf(state.results.keySet)) | 
| 79946 
05e034a54924
only start jobs early if they are due (cf. 1966578feff8);
 Fabian Huch <huch@in.tum.de> parents: 
79935diff
changeset | 595 | |
| 
05e034a54924
only start jobs early if they are due (cf. 1966578feff8);
 Fabian Huch <huch@in.tum.de> parents: 
79935diff
changeset | 596 | val waiting = other.filter(_.start.time <= now) | 
| 79921 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 597 | val running = state.running.values.toList.map(_.node_info).filter(_.hostname == hostname) | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 598 | |
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 599 |       def try_run(ready: List[Schedule.Node], next: Schedule.Node): List[Schedule.Node] = {
 | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 600 | val existing = ready.map(_.node_info) ::: running | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 601 | val is_distinct = existing.forall(_.rel_cpus.intersect(next.node_info.rel_cpus).isEmpty) | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 602 | if (existing.forall(_.rel_cpus.nonEmpty) && is_distinct) next :: ready else ready | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 603 | } | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 604 | |
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 605 | waiting.foldLeft(ready)(try_run).map(_.job_name) | 
| 
1966578feff8
start scheduled jobs earlier, if possible;
 Fabian Huch <huch@in.tum.de> parents: 
79916diff
changeset | 606 | } | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 607 | |
| 79910 
fbfa7d25749a
tie-breaking in schedule optimization to pick best schedule even when run-time is dominated by large task (e.g., session with long timeout but no data yet);
 Fabian Huch <huch@in.tum.de> parents: 
79909diff
changeset | 608 | def exists_next(hostname: String, state: Build_Process.State): Boolean = | 
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 609 | next(hostname, state).nonEmpty | 
| 79911 | 610 | |
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 611 |     def update(state: Build_Process.State): Schedule = {
 | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 612 | val start1 = Date.now() | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 613 | |
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 614 | def shift_elapsed(graph: Schedule.Graph, name: String): Schedule.Graph = | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 615 |         graph.map_node(name, { node =>
 | 
| 79819 | 616 | val elapsed = start1 - state.running(name).start_date | 
| 79897 | 617 | node.copy(duration = (node.duration - elapsed).max(Time.zero)) | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 618 | }) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 619 | |
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 620 | def shift_starts(graph: Schedule.Graph, name: String): Schedule.Graph = | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 621 |         graph.map_node(name, { node =>
 | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 622 | val starts = start1 :: graph.imm_preds(node.job_name).toList.map(graph.get_node(_).end) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 623 | node.copy(start = starts.max(Date.Ordering)) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 624 | }) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 625 | |
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79819diff
changeset | 626 | val graph0 = | 
| 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79819diff
changeset | 627 | state.running.keys.foldLeft(graph.restrict(state.pending.isDefinedAt))(shift_elapsed) | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 628 | val graph1 = graph0.topological_order.foldLeft(graph0)(shift_starts) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 629 | |
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 630 | copy(start = start1, graph = graph1) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 631 | } | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 632 | } | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 633 | |
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 634 |   case class State(build_state: Build_Process.State, current_time: Time, finished: Schedule) {
 | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 635 | def start(config: Config): State = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 636 | copy(build_state = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 637 | build_state.copy(running = build_state.running + | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 638 | (config.job_name -> config.job_of(current_time)))) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 639 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 640 |     def step(timing_data: Timing_Data): State = {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 641 | val remaining = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 642 |         build_state.running.values.toList.map { job =>
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 643 | val elapsed = current_time - job.start_date.time | 
| 79026 
6585acdd6505
clarified time estimation: does not use config;
 Fabian Huch <huch@in.tum.de> parents: 
79025diff
changeset | 644 | val threads = timing_data.host_infos.num_threads(job.node_info) | 
| 
6585acdd6505
clarified time estimation: does not use config;
 Fabian Huch <huch@in.tum.de> parents: 
79025diff
changeset | 645 | val predicted = timing_data.estimate(job.name, job.node_info.hostname, threads) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 646 | val remaining = if (elapsed > predicted) Time.zero else predicted - elapsed | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 647 | job -> remaining | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 648 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 649 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 650 |       if (remaining.isEmpty) error("Schedule step without running sessions")
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 651 |       else {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 652 | val (job, elapsed) = remaining.minBy(_._2.ms) | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 653 | val now = current_time + elapsed | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 654 | val node = Schedule.Node(job.name, job.node_info, job.start_date, now - job.start_date.time) | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 655 | |
| 79191 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 656 | val host_preds = | 
| 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 657 |           for {
 | 
| 79594 | 658 | name <- finished.graph.keys | 
| 659 | pred_node = finished.graph.get_node(name) | |
| 79236 
6dc4fd89987f
filter predecessors properly (amending ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79235diff
changeset | 660 | if pred_node.node_info.hostname == job.node_info.hostname | 
| 
6dc4fd89987f
filter predecessors properly (amending ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79235diff
changeset | 661 | if pred_node.end.time <= node.start.time | 
| 79191 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 662 | } yield name | 
| 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 663 | val build_preds = | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 664 | build_state.sessions.graph.imm_preds(job.name).filter(finished.graph.defined) | 
| 79191 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 665 | val preds = build_preds ++ host_preds | 
| 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 666 | |
| 
ee405c40db72
store previous build jobs in graph so schedules can be used later in the build process;
 Fabian Huch <huch@in.tum.de> parents: 
79190diff
changeset | 667 | val graph = preds.foldLeft(finished.graph.new_node(job.name, node))(_.add_edge(_, job.name)) | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 668 | |
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 669 | val build_state1 = build_state.remove_running(job.name).remove_pending(job.name) | 
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 670 | State(build_state1, now, finished.copy(graph = graph)) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 671 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 672 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 673 | |
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 674 | def is_finished: Boolean = build_state.pending.isEmpty && build_state.running.isEmpty | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 675 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 676 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 677 |   trait Scheduler { def schedule(build_state: Build_Process.State): Schedule }
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 678 | |
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 679 |   trait Priority_Rule { def select_next(state: Build_Process.State): List[Config] }
 | 
| 78931 
26841d3c568c
performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
78930diff
changeset | 680 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 681 | case class Generation_Scheme( | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 682 | priority_rule: Priority_Rule, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 683 | timing_data: Timing_Data, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 684 | build_uuid: String | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 685 |   ) extends Scheduler {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 686 |     def schedule(build_state: Build_Process.State): Schedule = {
 | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 687 | @tailrec | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 688 | def simulate(state: State): State = | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 689 | if (state.is_finished) state | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 690 |         else {
 | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 691 | val state1 = | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 692 | priority_rule | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 693 | .select_next(state.build_state) | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 694 | .foldLeft(state)(_.start(_)) | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 695 | .step(timing_data) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 696 | simulate(state1) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 697 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 698 | |
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 699 | val start = Date.now() | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 700 |       val name = "generation scheme (" + priority_rule + ")"
 | 
| 79109 
c1255d9870f6
clarified heuristics toString;
 Fabian Huch <huch@in.tum.de> parents: 
79108diff
changeset | 701 | val end_state = | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 702 | simulate(State(build_state, start.time, Schedule(build_uuid, name, start, Graph.empty))) | 
| 79073 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 703 | |
| 
b3fee0dafd72
generated build schedule explicitly (e.g., for further analysis);
 Fabian Huch <huch@in.tum.de> parents: 
79064diff
changeset | 704 | end_state.finished | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 705 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 706 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 707 | |
| 79928 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 708 |   case class Optimizer(schedulers: List[Scheduler], schedules: List[Schedule]) extends Scheduler {
 | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 709 | require(schedulers.nonEmpty) | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 710 | |
| 79805 
45198ea3f0b3
parallelize schedule optimization;
 Fabian Huch <huch@in.tum.de> parents: 
79785diff
changeset | 711 |     def schedule(state: Build_Process.State): Schedule = {
 | 
| 
45198ea3f0b3
parallelize schedule optimization;
 Fabian Huch <huch@in.tum.de> parents: 
79785diff
changeset | 712 | def main(scheduler: Scheduler): Schedule = scheduler.schedule(state) | 
| 79928 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 713 | (Par_List.map(main, schedulers) ::: schedules.map(_.update(state))).minBy(schedule => | 
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 714 | schedule.durations.map(_.ms).sorted.reverse) | 
| 79805 
45198ea3f0b3
parallelize schedule optimization;
 Fabian Huch <huch@in.tum.de> parents: 
79785diff
changeset | 715 | } | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 716 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 717 | |
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 718 | |
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 719 | /* priority rules */ | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 720 | |
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 721 |   class Default_Heuristic(host_infos: Host_Infos) extends Priority_Rule {
 | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 722 | override def toString: String = "default heuristic" | 
| 79107 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 723 | |
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 724 | def next_jobs(resources: Resources, sorted_jobs: List[String], host: Host): List[Config] = | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 725 | sorted_jobs.zip(resources.unused_nodes(host, host.max_threads)).map(Config(_, _)) | 
| 79107 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 726 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 727 |     def select_next(state: Build_Process.State): List[Config] = {
 | 
| 79107 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 728 | val sorted_jobs = state.next_ready.sortBy(_.name)(state.sessions.ordering).map(_.name) | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 729 | val resources = host_infos.available(state) | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 730 | |
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 731 |       host_infos.hosts.foldLeft((sorted_jobs, List.empty[Config])) {
 | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 732 | case ((jobs, res), host) => | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 733 | val configs = next_jobs(resources, jobs, host) | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 734 | val config_jobs = configs.map(_.job_name).toSet | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 735 | (jobs.filterNot(config_jobs.contains), configs ::: res) | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 736 | }._2 | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 737 | } | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 738 | } | 
| 
f5a2f956b531
add heuristic for non-scheduled (standard) build behaviour;
 Fabian Huch <huch@in.tum.de> parents: 
79106diff
changeset | 739 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 740 |   object Path_Time_Heuristic {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 741 | sealed trait Critical_Criterion | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 742 |     case class Absolute_Time(time: Time) extends Critical_Criterion {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 743 |       override def toString: String = "absolute time (" + time.message_hms + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 744 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 745 |     case class Relative_Time(factor: Double) extends Critical_Criterion {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 746 |       override def toString: String = "relative time (" + factor + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 747 | } | 
| 78931 
26841d3c568c
performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
78930diff
changeset | 748 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 749 | sealed trait Parallel_Strategy | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 750 |     case class Fixed_Thread(threads: Int) extends Parallel_Strategy {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 751 |       override def toString: String = "fixed threads (" + threads + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 752 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 753 |     case class Time_Based_Threads(f: Time => Int) extends Parallel_Strategy {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 754 | override def toString: String = "time based threads" | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 755 | } | 
| 78931 
26841d3c568c
performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
78930diff
changeset | 756 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 757 | sealed trait Host_Criterion | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 758 |     case object Critical_Nodes extends Host_Criterion {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 759 | override def toString: String = "per critical node" | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 760 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 761 |     case class Fixed_Fraction(fraction: Double) extends Host_Criterion {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 762 |       override def toString: String = "fixed fraction (" + fraction + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 763 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 764 |     case class Host_Speed(min_factor: Double) extends Host_Criterion {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 765 |       override def toString: String = "host speed (" + min_factor + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 766 | } | 
| 78931 
26841d3c568c
performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
78930diff
changeset | 767 | } | 
| 
26841d3c568c
performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
78930diff
changeset | 768 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 769 | class Path_Time_Heuristic( | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 770 | is_critical: Path_Time_Heuristic.Critical_Criterion, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 771 | parallel_threads: Path_Time_Heuristic.Parallel_Strategy, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 772 | host_criterion: Path_Time_Heuristic.Host_Criterion, | 
| 79027 
d08fb157e300
use proper max threads (limited by available hardware) in heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
79026diff
changeset | 773 | timing_data: Timing_Data, | 
| 
d08fb157e300
use proper max threads (limited by available hardware) in heuristics;
 Fabian Huch <huch@in.tum.de> parents: 
79026diff
changeset | 774 | sessions_structure: Sessions.Structure, | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 775 | max_threads_limit: Int = 8 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 776 |   ) extends Priority_Rule {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 777 | import Path_Time_Heuristic.* | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 778 | |
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 779 |     override def toString: Node = {
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 780 | val params = | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 781 | List( | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 782 | "critical: " + is_critical, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 783 | "parallel: " + parallel_threads, | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 784 | "fast hosts: " + host_criterion) | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 785 |       "path time heuristic (" + params.mkString(", ") + ")"
 | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 786 | } | 
| 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 787 | |
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 788 | /* pre-computed properties for efficient heuristic */ | 
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 789 | val host_infos: Host_Infos = timing_data.host_infos | 
| 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 790 | val ordered_hosts: List[Host] = host_infos.hosts.sorted(host_infos.host_speeds) | 
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 791 | |
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 792 | val max_threads: Int = host_infos.hosts.map(_.max_threads).max min max_threads_limit | 
| 79102 | 793 | |
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 794 | type Node = String | 
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 795 | val build_graph: Graph[Node, Sessions.Info] = sessions_structure.build_graph | 
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 796 | |
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 797 | val minimals: List[Node] = build_graph.minimals | 
| 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 798 | val maximals: List[Node] = build_graph.maximals | 
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 799 | |
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 800 | val best_threads: Map[Node, Int] = | 
| 79594 | 801 | build_graph.keys.map(node => node -> timing_data.best_threads(node, max_threads)).toMap | 
| 802 | ||
| 79102 | 803 |     def best_time(node: Node): Time = {
 | 
| 804 | val host = ordered_hosts.last | |
| 79927 
4359257218ce
clarify use of num_threads vs. max_cpus;
 Fabian Huch <huch@in.tum.de> parents: 
79926diff
changeset | 805 | val threads = best_threads(node) min host.max_threads | 
| 79103 
883f61f0beda
clarified build schedule host: more operations;
 Fabian Huch <huch@in.tum.de> parents: 
79102diff
changeset | 806 | timing_data.estimate(node, host.name, threads) | 
| 79102 | 807 | } | 
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 808 | val best_times: Map[Node, Time] = build_graph.keys.map(node => node -> best_time(node)).toMap | 
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 809 | |
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 810 | val succs_max_time_ms: Map[Node, Long] = build_graph.node_height(best_times(_).ms) | 
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 811 | def max_time(node: Node): Time = Time.ms(succs_max_time_ms(node)) + best_times(node) | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 812 | def max_time(task: Build_Process.Task): Time = max_time(task.name) | 
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 813 | |
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 814 |     def path_times(minimals: List[Node]): Map[Node, Time] = {
 | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 815 | def time_ms(node: Node): Long = best_times(node).ms | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 816 | val path_times_ms = build_graph.reachable_length(time_ms, build_graph.imm_succs, minimals) | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 817 | path_times_ms.view.mapValues(Time.ms).toMap | 
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 818 | } | 
| 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 819 | |
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 820 | def path_max_times(minimals: List[Node]): Map[Node, Time] = | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 821 | path_times(minimals).toList.map((node, time) => node -> (time + max_time(node))).toMap | 
| 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 822 | |
| 79713 
d3a26436e679
tuned signature: more types, fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79703diff
changeset | 823 | val node_degrees: Map[Node, Int] = | 
| 79594 | 824 | build_graph.keys.map(node => node -> build_graph.imm_succs(node).size).toMap | 
| 78972 
7a39f151e9a7
proper parallel paths for timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
78971diff
changeset | 825 | |
| 79594 | 826 | def parallel_paths( | 
| 827 | running: List[(Node, Time)], | |
| 828 | nodes: Set[Node] = build_graph.keys.toSet, | |
| 829 | max: Int = Int.MaxValue | |
| 830 | ): Int = | |
| 831 | if (nodes.nonEmpty && nodes.map(node_degrees.apply).max > max) max | |
| 832 |       else {
 | |
| 833 | def start(node: Node): (Node, Time) = node -> best_times(node) | |
| 834 | ||
| 835 | def pass_time(elapsed: Time)(node: Node, time: Time): (Node, Time) = | |
| 836 | node -> (time - elapsed) | |
| 78972 
7a39f151e9a7
proper parallel paths for timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
78971diff
changeset | 837 | |
| 79594 | 838 | def parallel_paths(running: Map[Node, Time]): (Int, Map[Node, Time]) = | 
| 839 | if (running.size >= max) (max, running) | |
| 840 | else if (running.isEmpty) (0, running) | |
| 841 |           else {
 | |
| 842 | def get_next(node: Node): List[Node] = | |
| 843 | build_graph.imm_succs(node).intersect(nodes).filter( | |
| 844 | build_graph.imm_preds(_).intersect(running.keySet) == Set(node)).toList | |
| 78972 
7a39f151e9a7
proper parallel paths for timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
78971diff
changeset | 845 | |
| 79594 | 846 | val (next, elapsed) = running.minBy(_._2.ms) | 
| 847 | val (remaining, finished) = | |
| 848 | running.toList.map(pass_time(elapsed)).partition(_._2 > Time.zero) | |
| 78972 
7a39f151e9a7
proper parallel paths for timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
78971diff
changeset | 849 | |
| 79594 | 850 | val running1 = | 
| 851 | remaining.map(pass_time(elapsed)).toMap ++ | |
| 852 | finished.map(_._1).flatMap(get_next).map(start) | |
| 853 | val (res, running2) = parallel_paths(running1) | |
| 854 | (res max running.size, running2) | |
| 855 | } | |
| 856 | ||
| 857 | parallel_paths(running.toMap)._1 | |
| 858 | } | |
| 78929 
df323f23dfde
performance tuning for timing heuristic: pre-calculate graph operations;
 Fabian Huch <huch@in.tum.de> parents: 
78928diff
changeset | 859 | |
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 860 |     def select_next(state: Build_Process.State): List[Config] = {
 | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 861 | val resources = host_infos.available(state) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 862 | |
| 79594 | 863 | def best_threads(task: Build_Process.Task): Int = this.best_threads(task.name) | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 864 | |
| 79028 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 865 | val rev_ordered_hosts = ordered_hosts.reverse.map(_ -> max_threads) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 866 | |
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 867 | val available_nodes = | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 868 | host_infos.available(state.copy(running = Map.empty)) | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 869 | .unused_nodes(max_threads) | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 870 | .sortBy(node => host_infos.the_host(node))(host_infos.host_speeds).reverse | 
| 79179 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 871 | |
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 872 | def remaining_time(node: Node): (Node, Time) = | 
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 873 |         state.running.get(node) match {
 | 
| 79594 | 874 | case None => node -> best_times(node) | 
| 79179 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 875 | case Some(job) => | 
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 876 | val estimate = | 
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 877 | timing_data.estimate(job.name, job.node_info.hostname, | 
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 878 | host_infos.num_threads(job.node_info)) | 
| 79184 | 879 | node -> ((Time.now() - job.start_date.time + estimate) max Time.zero) | 
| 79179 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 880 | } | 
| 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 881 | |
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 882 | val next_sorted = state.next_ready.sortBy(max_time(_).ms).reverse | 
| 79594 | 883 | val is_parallelizable = | 
| 884 | available_nodes.length >= parallel_paths( | |
| 885 | state.ready.map(_.name).map(remaining_time), | |
| 886 | max = available_nodes.length + 1) | |
| 79088 | 887 | |
| 79594 | 888 |       if (is_parallelizable) {
 | 
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 889 | val all_tasks = next_sorted.map(task => (task, best_threads(task), best_threads(task))) | 
| 79028 
6bada416ba55
clarified timing data operations: proper estimation (instead of known points);
 Fabian Huch <huch@in.tum.de> parents: 
79027diff
changeset | 890 | resources.try_allocate_tasks(rev_ordered_hosts, all_tasks)._1 | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 891 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 892 |       else {
 | 
| 79110 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 893 | def is_critical(time: Time): Boolean = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 894 |           this.is_critical match {
 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 895 | case Absolute_Time(threshold) => time > threshold | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 896 | case Relative_Time(factor) => time > minimals.map(max_time).maxBy(_.ms).scale(factor) | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 897 | } | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 898 | |
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 899 | val critical_minimals = state.ready.filter(task => is_critical(max_time(task))).map(_.name) | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 900 | val critical_nodes = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 901 | path_max_times(critical_minimals).filter((_, time) => is_critical(time)).keySet | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 902 | |
| 79101 
4e47b34fbb8e
clarified graph operations in timing heuristic;
 Fabian Huch <huch@in.tum.de> parents: 
79091diff
changeset | 903 | val (critical, other) = next_sorted.partition(task => critical_nodes.contains(task.name)) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 904 | |
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 905 | val critical_tasks = critical.map(task => (task, best_threads(task), best_threads(task))) | 
| 79110 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 906 | |
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 907 | def parallel_threads(task: Build_Process.Task): Int = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 908 |           this.parallel_threads match {
 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 909 | case Fixed_Thread(threads) => threads | 
| 79594 | 910 | case Time_Based_Threads(f) => f(best_times(task.name)) | 
| 79110 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 911 | } | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 912 | |
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 913 | val other_tasks = other.map(task => (task, parallel_threads(task), best_threads(task))) | 
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 914 | |
| 79179 
7ed43417770f
proper parallel paths: factor in elapsed time;
 Fabian Huch <huch@in.tum.de> parents: 
79178diff
changeset | 915 | val max_critical_parallel = | 
| 79594 | 916 | parallel_paths(critical_minimals.map(remaining_time), critical_nodes) | 
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 917 | val max_critical_hosts = | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 918 | available_nodes.take(max_critical_parallel).map(_.hostname).distinct.length | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 919 | |
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 920 | val split = | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 921 |           this.host_criterion match {
 | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 922 | case Critical_Nodes => max_critical_hosts | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 923 | case Fixed_Fraction(fraction) => | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 924 | ((rev_ordered_hosts.length * fraction).ceil.toInt max 1) min max_critical_hosts | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 925 | case Host_Speed(min_factor) => | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 926 | val best = rev_ordered_hosts.head._1.benchmark_score | 
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 927 | val num_fast = | 
| 79880 
a3d53f2bc41d
clarified build schedule host: proper module;
 Fabian Huch <huch@in.tum.de> parents: 
79879diff
changeset | 928 | rev_ordered_hosts.count(_._1.benchmark_score >= best * min_factor) | 
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 929 | num_fast min max_critical_hosts | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 930 | } | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 931 | |
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 932 | val (critical_hosts, other_hosts) = rev_ordered_hosts.splitAt(split) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 933 | |
| 78971 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 934 | val (configs1, resources1) = resources.try_allocate_tasks(critical_hosts, critical_tasks) | 
| 
f930d24f1548
scheduled build: allocate cpus more aggressively, to avoid idle threads;
 Fabian Huch <huch@in.tum.de> parents: 
78970diff
changeset | 935 | val (configs2, _) = resources1.try_allocate_tasks(other_hosts, other_tasks) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 936 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 937 | configs1 ::: configs2 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 938 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 939 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 940 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 941 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 942 | |
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 943 | /* master and slave processes for scheduled build */ | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 944 | |
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 945 | class Scheduled_Build_Process( | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 946 | build_context: Build.Context, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 947 | build_progress: Progress, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 948 | server: SSH.Server, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 949 |   ) extends Build_Process(build_context, build_progress, server) {
 | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 950 | /* global state: internal var vs. external database */ | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 951 | |
| 79649 
981cd49a3f90
more explicit types --- fewer warnings in IntelliJ IDEA;
 wenzelm parents: 
79648diff
changeset | 952 | protected var _schedule: Schedule = Schedule.init(build_uuid) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 953 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 954 | override protected def synchronized_database[A](label: String)(body: => A): A = | 
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 955 |       synchronized {
 | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 956 |         _build_database match {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 957 | case None => body | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 958 | case Some(db) => | 
| 79761 | 959 |             db.transaction_lock(Build_Schedule.private_data.all_tables, label = label) {
 | 
| 79871 
630a82f87310
database performance tuning: pull changed entries only, based on recorded updates (see 98d65411bfdb);
 wenzelm parents: 
79867diff
changeset | 960 | val old_state = | 
| 79904 | 961 | Build_Process.private_data.pull_state(db, build_id, worker_uuid, _state) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 962 | val old_schedule = Build_Schedule.private_data.pull_schedule(db, _schedule) | 
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 963 | _state = old_state | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 964 | _schedule = old_schedule | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 965 | val res = body | 
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 966 | _state = | 
| 79904 | 967 | Build_Process.private_data.push_state( | 
| 79850 
8ffcaf563745
maintain short build_id vs. build_uuid, similar to Database_Progress context/context_uuid;
 wenzelm parents: 
79844diff
changeset | 968 | db, build_id, worker_uuid, _state, old_state) | 
| 79904 | 969 | _schedule = Build_Schedule.private_data.pull_schedule(db, _schedule, old_schedule) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 970 | res | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 971 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 972 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 973 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 974 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 975 | |
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 976 | /* build process */ | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 977 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 978 | override def next_node_info(state: Build_Process.State, session_name: String): Node_Info = | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 979 | _schedule.graph.get_node(session_name).node_info | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 980 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 981 | override def next_jobs(state: Build_Process.State): List[String] = | 
| 79294 
ae0a2cb42b05
continue build while waiting for updated schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79293diff
changeset | 982 | if (progress.stopped || _schedule.is_empty) Nil else _schedule.next(hostname, state) | 
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 983 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 984 | private var _build_tick: Long = 0L | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 985 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 986 | protected override def build_action(): Boolean = | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 987 |       Isabelle_Thread.interrupt_handler(_ => progress.stop()) {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 988 | val received = build_receive(n => n.channel == Build_Process.private_data.channel) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 989 | val ready = received.contains(Build_Schedule.private_data.channel_ready(hostname)) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 990 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 991 |         val finished = synchronized { _state.finished_running() }
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 992 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 993 |         def sleep: Boolean = {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 994 | build_delay.sleep() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 995 |           val expired = synchronized { _build_tick += 1; _build_tick % build_expire == 0 }
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 996 | expired || ready || progress.stopped | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 997 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 998 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 999 | finished || sleep | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1000 | } | 
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1001 | } | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1002 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1003 | abstract class Scheduler_Build_Process( | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1004 | build_context: Build.Context, | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1005 | build_progress: Progress, | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1006 | server: SSH.Server, | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1007 |   ) extends Scheduled_Build_Process(build_context, build_progress, server) {
 | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1008 | require(build_context.master) | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1009 | |
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1010 |     for (db <- _build_database) {
 | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1011 | Build_Schedule.private_data.transaction_lock( | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1012 | db, | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1013 | create = true, | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1014 | label = "Scheduler_Build_Process.create" | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1015 |       ) { Build_Schedule.private_data.clean_build_schedules(db) }
 | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1016 | db.vacuum(Build_Schedule.private_data.tables.list) | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1017 | } | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1018 | |
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1019 | |
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1020 | def init_scheduler(timing_data: Timing_Data): Scheduler | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1021 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1022 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1023 | /* global resources with common close() operation */ | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1024 | |
| 79934 
502525a82d9f
remove laziness: no need, and errors during initialization loop with close();
 Fabian Huch <huch@in.tum.de> parents: 
79931diff
changeset | 1025 | private final val _log_store: Build_Log.Store = Build_Log.store(build_options) | 
| 
502525a82d9f
remove laziness: no need, and errors during initialization loop with close();
 Fabian Huch <huch@in.tum.de> parents: 
79931diff
changeset | 1026 | private final val _log_database: SQL.Database = | 
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1027 |       try {
 | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1028 | val db = _log_store.open_database(server = this.server) | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1029 | _log_store.init_database(db) | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1030 | db | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1031 | } | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1032 |       catch { case exn: Throwable => close(); throw exn }
 | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1033 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1034 |     override def close(): Unit = {
 | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1035 | Option(_log_database).foreach(_.close()) | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1036 | super.close() | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1037 | } | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1038 | |
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1039 | |
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1040 | /* previous results via build log */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1041 | |
| 79765 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1042 |     override def open_build_cluster(): Build_Cluster = {
 | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1043 | val build_cluster = super.open_build_cluster() | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1044 | build_cluster.init() | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1045 | |
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1046 | Build_Benchmark.benchmark_requirements(build_options) | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1047 | |
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1048 |       if (build_context.worker) {
 | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1049 |         val benchmark_options = build_options.string("build_hostname") = hostname
 | 
| 79947 
5eb90c1ce653
add hosts option to run benchmark on the cluster from the command-line;
 Fabian Huch <huch@in.tum.de> parents: 
79946diff
changeset | 1050 | Build_Benchmark.run_benchmark(benchmark_options, progress) | 
| 79765 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1051 | } | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1052 | |
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1053 | build_cluster.benchmark() | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1054 | } | 
| 
a478fc5cd5bd
partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
 Fabian Huch <huch@in.tum.de> parents: 
79761diff
changeset | 1055 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1056 |     private var _host_infos = {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1057 | val build_hosts = | 
| 79878 | 1058 | if (!build_context.worker) build_context.build_hosts | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1059 |         else {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1060 | val local_build_host = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1061 | Build_Cluster.Host( | 
| 79616 | 1062 | hostname, jobs = build_context.jobs, numa = build_context.numa_shuffling) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1063 | local_build_host :: build_context.build_hosts | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1064 | } | 
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1065 | Host_Infos.load(build_options, build_hosts, _host_database) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1066 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1067 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1068 |     private val timing_data: Timing_Data = {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1069 | Timing_Data.load(_host_infos, _log_database, build_context.sessions_structure) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1070 | } | 
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1071 | |
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1072 | private var _scheduler = init_scheduler(timing_data) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1073 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1074 |     def write_build_log(results: Build.Results, state: Build_Process.State.Results): Unit = {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1075 | val sessions = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1076 |         for {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1077 | (session_name, result) <- state.toList | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1078 | if !result.current | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1079 |         } yield {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1080 | val info = build_context.sessions_structure(session_name) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1081 | val entry = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1082 |             if (!results.cancelled(session_name)) {
 | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1083 | val status = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1084 | if (result.ok) Build_Log.Session_Status.finished | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1085 | else Build_Log.Session_Status.failed | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1086 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1087 | Build_Log.Session_Entry( | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1088 | chapter = info.chapter, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1089 | groups = info.groups, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1090 | hostname = Some(result.node_info.hostname), | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1091 | threads = Some(timing_data.host_infos.num_threads(result.node_info)), | 
| 79892 
c793de82db34
track start in build job results (following 9d484c5d3a63), so it can directly be written to build log database;
 Fabian Huch <huch@in.tum.de> parents: 
79891diff
changeset | 1092 | start = Some(result.start_date - build_start), | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1093 | timing = result.process_result.timing, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1094 | sources = Some(result.output_shasum.digest.toString), | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1095 | status = Some(status)) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1096 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1097 | else | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1098 | Build_Log.Session_Entry( | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1099 | chapter = info.chapter, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1100 | groups = info.groups, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1101 | status = Some(Build_Log.Session_Status.cancelled)) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1102 | session_name -> entry | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1103 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1104 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1105 | val settings = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1106 | Build_Log.Settings.all_settings.map(_.name).map(name => | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1107 | name -> Isabelle_System.getenv(name)) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1108 | val props = | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1109 | List( | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1110 | Build_Log.Prop.build_id.name -> build_context.build_uuid, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1111 | Build_Log.Prop.build_engine.name -> build_context.engine.name, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1112 | Build_Log.Prop.build_host.name -> hostname, | 
| 79891 
d8b4bfe82bb5
use inherited build_start, following d9fc2cc37694;
 Fabian Huch <huch@in.tum.de> parents: 
79880diff
changeset | 1113 | Build_Log.Prop.build_start.name -> Build_Log.print_date(build_start)) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1114 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1115 | val meta_info = Build_Log.Meta_Info(props, settings) | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1116 | val build_info = Build_Log.Build_Info(sessions.toMap) | 
| 79891 
d8b4bfe82bb5
use inherited build_start, following d9fc2cc37694;
 Fabian Huch <huch@in.tum.de> parents: 
79880diff
changeset | 1117 | val log_name = Build_Log.log_filename(engine = build_context.engine.name, date = build_start) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1118 | |
| 79062 
6977fb0153fb
clarified modules: Build_Log.private_data provides raw data access without transaction_lock;
 wenzelm parents: 
79042diff
changeset | 1119 | Build_Log.private_data.update_sessions( | 
| 
6977fb0153fb
clarified modules: Build_Log.private_data provides raw data access without transaction_lock;
 wenzelm parents: 
79042diff
changeset | 1120 | _log_database, _log_store.cache.compress, log_name.file_name, build_info) | 
| 
6977fb0153fb
clarified modules: Build_Log.private_data provides raw data access without transaction_lock;
 wenzelm parents: 
79042diff
changeset | 1121 | Build_Log.private_data.update_meta_info(_log_database, log_name.file_name, meta_info) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1122 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1123 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1124 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1125 | /* build process */ | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1126 | |
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1127 | def is_current(state: Build_Process.State, session_name: String): Boolean = | 
| 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1128 |       state.ancestor_results(session_name) match {
 | 
| 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1129 | case Some(ancestor_results) if ancestor_results.forall(_.current) => | 
| 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1130 | store.check_output( | 
| 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1131 | _database_server, session_name, | 
| 80125 | 1132 | sources_shasum = state.sessions(session_name).sources_shasum, | 
| 1133 | input_shasum = ML_Process.make_shasum(ancestor_results.map(_.output_shasum)), | |
| 80128 | 1134 | build_thorough = build_context.sessions_structure(session_name).build_thorough, | 
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1135 | fresh_build = build_context.fresh_build, | 
| 80125 | 1136 | store_heap = build_context.store_heap || state.sessions.store_heap(session_name))._1 | 
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1137 | case _ => false | 
| 79911 | 1138 | } | 
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1139 | |
| 79192 
5db03f9276e2
clarified: build schedules may be outdated when empty, after some time, or due to build progress;
 Fabian Huch <huch@in.tum.de> parents: 
79191diff
changeset | 1140 | override def next_jobs(state: Build_Process.State): List[String] = | 
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1141 | if (progress.stopped) state.next_ready.map(_.name) | 
| 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1142 | else if (!_schedule.is_outdated(build_options, state)) _schedule.next(hostname, state) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1143 |       else {
 | 
| 79020 
ef76705bf402
clarified ready vs. next ready;
 Fabian Huch <huch@in.tum.de> parents: 
79019diff
changeset | 1144 | val current = state.next_ready.filter(task => is_current(state, task.name)) | 
| 79187 | 1145 | if (current.nonEmpty) current.map(_.name) | 
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1146 |         else {
 | 
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1147 | val start = Date.now() | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1148 | |
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1149 |           def completed_since(name: String): Time = {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1150 | val result = state.results(name) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1151 | start - (result.start_date + result.process_result.timing.elapsed) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1152 | } | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 1153 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1154 | val active_hosts0 = (for ((_, job) <- state.running) yield job.node_info.hostname).toSet | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1155 | val inactive_hosts = | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1156 |             (for {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1157 | host <- _host_infos.hosts | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1158 | if !active_hosts0.contains(host.name) | 
| 80476 
59e088605d49
only consider jobs late if they have ancestors (amending 12901c03b416);
 Fabian Huch <huch@in.tum.de> parents: 
80471diff
changeset | 1159 | ancestors = _schedule.next(host.name, state).flatMap(_schedule.graph.imm_preds) | 
| 
59e088605d49
only consider jobs late if they have ancestors (amending 12901c03b416);
 Fabian Huch <huch@in.tum.de> parents: 
80471diff
changeset | 1160 | if ancestors.nonEmpty && ancestors.forall(ancestor => | 
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1161 |                 completed_since(ancestor) > build_options.seconds("build_schedule_inactive_delay"))
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1162 | } yield host).toSet | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1163 | |
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1164 | val host_infos = Host_Infos(_host_infos.hosts.filterNot(inactive_hosts.contains)) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1165 |           if (host_infos != _host_infos) {
 | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1166 | _host_infos = host_infos | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1167 | _scheduler = init_scheduler(Timing_Data.restrict(timing_data, host_infos)) | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1168 | } | 
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1169 | |
| 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1170 | val new_schedule = _scheduler.schedule(state).update(state) | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 1171 | val schedule = | 
| 79293 | 1172 | if (_schedule.is_empty) new_schedule | 
| 79193 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 1173 | else List(_schedule.update(state), new_schedule).minBy(_.end)(Date.Ordering) | 
| 
d1d6dbab2901
compare previous build schedule with new one, to prevent regressions;
 Fabian Huch <huch@in.tum.de> parents: 
79192diff
changeset | 1174 | |
| 80471 
12901c03b416
remove inactive (e.g., crashed) hosts from scheduling;
 Fabian Huch <huch@in.tum.de> parents: 
80274diff
changeset | 1175 | val elapsed = Date.now() - start | 
| 78884 | 1176 | |
| 78976 | 1177 | val timing_msg = if (elapsed.is_relevant) " (took " + elapsed.message + ")" else "" | 
| 79935 
7a7f1d5dcfe9
only print schedule if relevant;
 Fabian Huch <huch@in.tum.de> parents: 
79934diff
changeset | 1178 | progress.echo_if( | 
| 
7a7f1d5dcfe9
only print schedule if relevant;
 Fabian Huch <huch@in.tum.de> parents: 
79934diff
changeset | 1179 | _schedule.deviation(schedule).minutes > 1 && schedule.duration >= Time.seconds(1), | 
| 
7a7f1d5dcfe9
only print schedule if relevant;
 Fabian Huch <huch@in.tum.de> parents: 
79934diff
changeset | 1180 | schedule.message + timing_msg) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1181 | |
| 79183 
32d00ec387f4
use schedule directly instead of extra cache;
 Fabian Huch <huch@in.tum.de> parents: 
79182diff
changeset | 1182 | _schedule = schedule | 
| 
32d00ec387f4
use schedule directly instead of extra cache;
 Fabian Huch <huch@in.tum.de> parents: 
79182diff
changeset | 1183 | _schedule.next(hostname, state) | 
| 78969 
1b05c2b10c9f
finalize current sessions before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
78968diff
changeset | 1184 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1185 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1186 | |
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1187 |     override def run(): Build.Results = {
 | 
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1188 | val vacuous = | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1189 |         synchronized_database("Scheduler_Build_Process.init") {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1190 | for (db <- _build_database) Build_Process.private_data.clean_build(db) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1191 | init_unsynchronized() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1192 | _state.pending.isEmpty | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1193 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1194 |       if (vacuous) {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1195 |         progress.echo_warning("Nothing to build")
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1196 | stop_build() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1197 | Build.Results(build_context) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1198 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1199 |       else {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1200 | start_worker() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1201 | _build_cluster.start() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1202 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1203 |         try {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1204 |           while (!finished()) {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1205 |             synchronized_database("Scheduler_Build_Process.main") {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1206 | if (progress.stopped) _state.build_running.foreach(_.cancel()) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1207 | main_unsynchronized() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1208 |               for {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1209 | host <- build_context.build_hosts | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1210 | if _schedule.exists_next(host.name, _state) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1211 | } build_send(Build_Schedule.private_data.channel_ready(host.name)) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1212 | } | 
| 79911 | 1213 |             while (!build_action()) {}
 | 
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1214 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1215 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1216 |         finally {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1217 | _build_cluster.stop() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1218 | stop_worker() | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1219 | stop_build() | 
| 79527 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1220 | } | 
| 
f1f08ca40d96
make build process state protected to avoid copying in subclasses (e.g. for database connections);
 Fabian Huch <huch@in.tum.de> parents: 
79502diff
changeset | 1221 | |
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1222 |         val results = synchronized_database("Scheduler_Build_Process.result") {
 | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1223 | val results = for ((name, result) <- _state.results) yield name -> result.process_result | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1224 | Build.Results(build_context, results = results, other_rc = _build_cluster.rc) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1225 | } | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1226 | write_build_log(results, _state.results) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1227 | results | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1228 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1229 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1230 | } | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1231 | |
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1232 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1233 | /** SQL data model of build schedule, extending isabelle_build database */ | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1234 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1235 |   object private_data extends SQL.Data("isabelle_build") {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1236 |     import Build_Process.private_data.{Base, Generic}
 | 
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1237 | /* tables */ | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1238 | |
| 79844 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1239 | override lazy val tables: SQL.Tables = | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1240 | SQL.Tables(Schedules.table, Nodes.table) | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1241 | |
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1242 | lazy val all_tables: SQL.Tables = | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1243 | SQL.Tables.list(Build_Process.private_data.tables.list ::: tables.list) | 
| 
ac40138234ce
tuned signature: more uniform SQL.Data instances;
 wenzelm parents: 
79835diff
changeset | 1244 | |
| 79896 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1245 | /* notifications */ | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1246 | |
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1247 | def channel_ready(hostname: String): SQL.Notification = | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1248 | SQL.Notification(Build_Process.private_data.channel, payload = hostname) | 
| 
2c9c5ae99a09
proper IPC for scheduled builds, following 7ae25372ab04;
 Fabian Huch <huch@in.tum.de> parents: 
79895diff
changeset | 1249 | |
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1250 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1251 | /* schedule */ | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1252 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1253 |     object Schedules {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1254 | val build_uuid = Generic.build_uuid.make_primary_key | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1255 |       val generator = SQL.Column.string("generator")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1256 |       val start = SQL.Column.date("start")
 | 
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1257 |       val serial = SQL.Column.long("serial")
 | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1258 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1259 | val table = make_table(List(build_uuid, generator, start, serial), name = "schedules") | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1260 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1261 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1262 | def read_serial(db: SQL.Database, build_uuid: String = ""): Long = | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1263 | db.execute_query_statementO[Long]( | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1264 | Schedules.table.select(List(Schedules.serial.max), sql = | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1265 | SQL.where(if_proper(build_uuid, Schedules.build_uuid.equal(build_uuid)))), | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1266 | _.long(Schedules.serial)).getOrElse(0L) | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1267 | |
| 79832 
2a3c0a68221c
misc tuning: prefer Build_Process.Update operations;
 wenzelm parents: 
79829diff
changeset | 1268 | def read_scheduled_builds_domain(db: SQL.Database): Map[String, Unit] = | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1269 | db.execute_query_statement( | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1270 | Schedules.table.select(List(Schedules.build_uuid)), | 
| 79832 
2a3c0a68221c
misc tuning: prefer Build_Process.Update operations;
 wenzelm parents: 
79829diff
changeset | 1271 | Map.from[String, Unit], res => res.string(Schedules.build_uuid) -> ()) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1272 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1273 |     def read_schedules(db: SQL.Database, build_uuid: String = ""): List[Schedule] = {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1274 | val schedules = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1275 | db.execute_query_statement(Schedules.table.select(sql = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1276 | SQL.where(if_proper(build_uuid, Schedules.build_uuid.equal(build_uuid)))), | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1277 | List.from[Schedule], | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1278 |           { res =>
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1279 | val build_uuid = res.string(Schedules.build_uuid) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1280 | val generator = res.string(Schedules.generator) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1281 | val start = res.date(Schedules.start) | 
| 79287 
b88b6ed06334
read serial for schedules (amending 2039f360);
 Fabian Huch <huch@in.tum.de> parents: 
79236diff
changeset | 1282 | val serial = res.long(Schedules.serial) | 
| 
b88b6ed06334
read serial for schedules (amending 2039f360);
 Fabian Huch <huch@in.tum.de> parents: 
79236diff
changeset | 1283 | Schedule(build_uuid, generator, start, Graph.empty, serial) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1284 | }) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1285 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1286 |       for (schedule <- schedules.sortBy(_.start)(Date.Ordering)) yield {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1287 | val nodes = private_data.read_nodes(db, build_uuid = schedule.build_uuid) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1288 | schedule.copy(graph = Graph.make(nodes)) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1289 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1290 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1291 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1292 |     def write_schedule(db: SQL.Database, schedule: Schedule): Unit = {
 | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1293 | db.execute_statement( | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1294 | Schedules.table.delete(Schedules.build_uuid.where_equal(schedule.build_uuid))) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1295 |       db.execute_statement(Schedules.table.insert(), { stmt =>
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1296 | stmt.string(1) = schedule.build_uuid | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1297 | stmt.string(2) = schedule.generator | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1298 | stmt.date(3) = schedule.start | 
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1299 | stmt.long(4) = schedule.serial | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1300 | }) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1301 | update_nodes(db, schedule.build_uuid, schedule.graph.dest) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1302 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1303 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1304 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1305 | /* nodes */ | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1306 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1307 |     object Nodes {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1308 | val build_uuid = Generic.build_uuid.make_primary_key | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1309 | val name = Generic.name.make_primary_key | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1310 |       val succs = SQL.Column.string("succs")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1311 |       val hostname = SQL.Column.string("hostname")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1312 |       val numa_node = SQL.Column.int("numa_node")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1313 |       val rel_cpus = SQL.Column.string("rel_cpus")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1314 |       val start = SQL.Column.date("start")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1315 |       val duration = SQL.Column.long("duration")
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1316 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1317 | val table = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1318 | make_table( | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1319 | List(build_uuid, name, succs, hostname, numa_node, rel_cpus, start, duration), | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1320 | name = "schedule_nodes") | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1321 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1322 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1323 | type Nodes = List[((String, Schedule.Node), List[String])] | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1324 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1325 |     def read_nodes(db: SQL.Database, build_uuid: String = ""): Nodes = {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1326 | db.execute_query_statement( | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1327 | Nodes.table.select(sql = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1328 | SQL.where(if_proper(build_uuid, Nodes.build_uuid.equal(build_uuid)))), | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1329 | List.from[((String, Schedule.Node), List[String])], | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1330 |         { res =>
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1331 | val name = res.string(Nodes.name) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1332 | val succs = split_lines(res.string(Nodes.succs)) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1333 | val hostname = res.string(Nodes.hostname) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1334 | val numa_node = res.get_int(Nodes.numa_node) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1335 | val rel_cpus = res.string(Nodes.rel_cpus) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1336 | val start = res.date(Nodes.start) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1337 | val duration = Time.ms(res.long(Nodes.duration)) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1338 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1339 | val node_info = Node_Info(hostname, numa_node, isabelle.Host.Range.from(rel_cpus)) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1340 | ((name, Schedule.Node(name, node_info, start, duration)), succs) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1341 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1342 | ) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1343 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1344 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1345 |     def update_nodes(db: SQL.Database, build_uuid: String, nodes: Nodes): Unit = {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1346 | db.execute_statement(Nodes.table.delete(Nodes.build_uuid.where_equal(build_uuid))) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1347 | db.execute_batch_statement(Nodes.table.insert(), batch = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1348 |         for (((name, node), succs) <- nodes) yield { (stmt: SQL.Statement) =>
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1349 | stmt.string(1) = build_uuid | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1350 | stmt.string(2) = name | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1351 | stmt.string(3) = cat_lines(succs) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1352 | stmt.string(4) = node.node_info.hostname | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1353 | stmt.int(5) = node.node_info.numa_node | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1354 | stmt.string(6) = isabelle.Host.Range(node.node_info.rel_cpus) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1355 | stmt.date(7) = node.start | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1356 | stmt.long(8) = node.duration.ms | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1357 | }) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1358 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1359 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1360 |     def pull_schedule(db: SQL.Database, old_schedule: Schedule): Build_Schedule.Schedule = {
 | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1361 | val serial_db = read_serial(db) | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1362 | if (serial_db == old_schedule.serial) old_schedule | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1363 |       else {
 | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1364 |         read_schedules(db, old_schedule.build_uuid) match {
 | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1365 | case Nil => old_schedule | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1366 | case schedules => Library.the_single(schedules) | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1367 | } | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1368 | } | 
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1369 | } | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1370 | |
| 79904 | 1371 |     def pull_schedule(db: SQL.Database, schedule: Schedule, old_schedule: Schedule): Schedule = {
 | 
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1372 | val changed = | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1373 | schedule.generator != old_schedule.generator || | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1374 | schedule.start != old_schedule.start || | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1375 | schedule.graph != old_schedule.graph | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1376 | |
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1377 | val schedule1 = | 
| 79835 | 1378 | if (changed) schedule.copy(serial = old_schedule.next_serial) else schedule | 
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1379 | if (schedule1.serial != schedule.serial) write_schedule(db, schedule1) | 
| 79911 | 1380 | |
| 79190 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1381 | schedule1 | 
| 
2039f3609884
add serial for build schedule to avoid unnecessary db read/writes;
 Fabian Huch <huch@in.tum.de> parents: 
79189diff
changeset | 1382 | } | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1383 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1384 | def remove_schedules(db: SQL.Database, remove: List[String]): Unit = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1385 |       if (remove.nonEmpty) {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1386 | val sql = Generic.build_uuid.where_member(remove) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1387 | db.execute_statement(SQL.MULTI(tables.map(_.delete(sql = sql)))) | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1388 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1389 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1390 |     def clean_build_schedules(db: SQL.Database): Unit = {
 | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1391 | val running_builds_domain = | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1392 | db.execute_query_statement( | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1393 | Base.table.select(List(Base.build_uuid), sql = SQL.where(Base.stop.undefined)), | 
| 79832 
2a3c0a68221c
misc tuning: prefer Build_Process.Update operations;
 wenzelm parents: 
79829diff
changeset | 1394 | Map.from[String, Unit], res => res.string(Base.build_uuid) -> ()) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1395 | |
| 80274 | 1396 | val update = Update.make(read_scheduled_builds_domain(db), running_builds_domain) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1397 | |
| 79832 
2a3c0a68221c
misc tuning: prefer Build_Process.Update operations;
 wenzelm parents: 
79829diff
changeset | 1398 | remove_schedules(db, update.delete) | 
| 79186 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1399 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1400 | } | 
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1401 | |
| 
a22440b9cb70
use build database to synchronize build schedule computed on master node (e.g., such that view on cluster is consistent);
 Fabian Huch <huch@in.tum.de> parents: 
79185diff
changeset | 1402 | |
| 79640 
7a2b86a48be0
prefer static object, while class is required for "services";
 wenzelm parents: 
79639diff
changeset | 1403 |   class Build_Engine extends Build.Engine("build_schedule") {
 | 
| 79699 
b88d73810b50
recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
 wenzelm parents: 
79655diff
changeset | 1404 |     override def build_options(options: Options, build_cluster: Boolean = false): Options = {
 | 
| 
b88d73810b50
recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
 wenzelm parents: 
79655diff
changeset | 1405 | val options1 = super.build_options(options, build_cluster = build_cluster) | 
| 
b88d73810b50
recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
 wenzelm parents: 
79655diff
changeset | 1406 | if (build_cluster) options1 + "build_database_server" else options1 | 
| 
b88d73810b50
recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
 wenzelm parents: 
79655diff
changeset | 1407 | } | 
| 
b88d73810b50
recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
 wenzelm parents: 
79655diff
changeset | 1408 | |
| 79108 | 1409 |     def scheduler(timing_data: Timing_Data, context: Build.Context): Scheduler = {
 | 
| 1410 | val sessions_structure = context.sessions_structure | |
| 79110 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1411 | |
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1412 | val is_criticals = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1413 | List( | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1414 | Path_Time_Heuristic.Absolute_Time(Time.minutes(5)), | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1415 | Path_Time_Heuristic.Absolute_Time(Time.minutes(10)), | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1416 | Path_Time_Heuristic.Absolute_Time(Time.minutes(20)), | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1417 | Path_Time_Heuristic.Relative_Time(0.5)) | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1418 | val parallel_threads = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1419 | List( | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1420 | Path_Time_Heuristic.Fixed_Thread(1), | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1421 |           Path_Time_Heuristic.Time_Based_Threads({
 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1422 | case time if time < Time.minutes(1) => 1 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1423 | case time if time < Time.minutes(5) => 4 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1424 | case _ => 8 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1425 | })) | 
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1426 | val machine_splits = | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1427 | List( | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1428 | Path_Time_Heuristic.Critical_Nodes, | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1429 | Path_Time_Heuristic.Fixed_Fraction(0.3), | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1430 | Path_Time_Heuristic.Host_Speed(0.9)) | 
| 79110 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1431 | |
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1432 | val path_time_heuristics = | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1433 |         for {
 | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1434 | is_critical <- is_criticals | 
| 
ff68cbfa3550
clarified path time heuristic: configurable parameters for larger search space;
 Fabian Huch <huch@in.tum.de> parents: 
79109diff
changeset | 1435 | parallel <- parallel_threads | 
| 79180 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1436 | machine_split <- machine_splits | 
| 
229f49204603
clarified build heuristics parameters;
 Fabian Huch <huch@in.tum.de> parents: 
79179diff
changeset | 1437 | } yield | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 1438 | Path_Time_Heuristic(is_critical, parallel, machine_split, timing_data, sessions_structure) | 
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 1439 | val default_heuristic = Default_Heuristic(timing_data.host_infos) | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 1440 | val heuristics = default_heuristic :: path_time_heuristics | 
| 79928 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1441 | |
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1442 |       val initial_schedule_file = context.build_options.string("build_schedule_initial")
 | 
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1443 | val initial = | 
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1444 | proper_string(initial_schedule_file).toList.map(initial_schedule_file => | 
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1445 | Schedule.read(Path.explode(initial_schedule_file)).copy(build_uuid = context.build_uuid)) | 
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1446 | |
| 
cdc87eed26c7
allow specifying initial schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79927diff
changeset | 1447 | Optimizer(heuristics.map(Generation_Scheme(_, timing_data, context.build_uuid)), initial) | 
| 79089 | 1448 | } | 
| 1449 | ||
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1450 | override def open_build_process( | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1451 | context: Build.Context, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1452 | progress: Progress, | 
| 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1453 | server: SSH.Server | 
| 78928 
6c2c60b852e0
move timing data into scheduler for more efficient heuristics (e.g., with pre-calculated values);
 Fabian Huch <huch@in.tum.de> parents: 
78888diff
changeset | 1454 | ): Build_Process = | 
| 79290 
9deadc9d8872
separate build processes for scheduler and scheduled;
 Fabian Huch <huch@in.tum.de> parents: 
79289diff
changeset | 1455 | if (!context.master) new Scheduled_Build_Process(context, progress, server) | 
| 79915 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1456 |       else {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1457 |         val schedule_file = context.build_options.string("build_schedule")
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1458 |         if (schedule_file.isEmpty) {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1459 |           new Scheduler_Build_Process(context, progress, server) {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1460 | def init_scheduler(timing_data: Timing_Data): Scheduler = | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1461 | scheduler(timing_data, context) | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1462 | } | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1463 | } | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1464 |         else {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1465 | val finished_schedule = | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1466 | Schedule.read(Path.explode(schedule_file)).copy(build_uuid = context.build_uuid) | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1467 |           new Scheduler_Build_Process(context, progress, server) {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1468 | def init_scheduler(timing_data: Timing_Data): Scheduler = | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1469 | (build_state: Build_Process.State) => finished_schedule | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1470 | } | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1471 | } | 
| 78928 
6c2c60b852e0
move timing data into scheduler for more efficient heuristics (e.g., with pre-calculated values);
 Fabian Huch <huch@in.tum.de> parents: 
78888diff
changeset | 1472 | } | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1473 | } | 
| 79640 
7a2b86a48be0
prefer static object, while class is required for "services";
 wenzelm parents: 
79639diff
changeset | 1474 | object Build_Engine extends Build_Engine | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1475 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1476 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1477 | /* build schedule */ | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1478 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1479 | def build_schedule( | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1480 | options: Options, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1481 | build_hosts: List[Build_Cluster.Host] = Nil, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1482 | selection: Sessions.Selection = Sessions.Selection.empty, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1483 | progress: Progress = new Progress, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1484 | afp_root: Option[Path] = None, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1485 | dirs: List[Path] = Nil, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1486 | select_dirs: List[Path] = Nil, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1487 | infos: List[Sessions.Info] = Nil, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1488 | numa_shuffling: Boolean = false, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1489 | augment_options: String => List[Options.Spec] = _ => Nil, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1490 | session_setup: (String, Session) => Unit = (_, _) => (), | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1491 | cache: Term.Cache = Term.Cache.make() | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1492 |   ): Schedule = {
 | 
| 79908 
c50c15bd304b
remove old build before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79907diff
changeset | 1493 | Build.build_process(options, build_cluster = true, remove_builds = true) | 
| 
c50c15bd304b
remove old build before generating schedule;
 Fabian Huch <huch@in.tum.de> parents: 
79907diff
changeset | 1494 | |
| 79614 | 1495 | val store = | 
| 79640 
7a2b86a48be0
prefer static object, while class is required for "services";
 wenzelm parents: 
79639diff
changeset | 1496 | Build_Engine.build_store(options, build_cluster = build_hosts.nonEmpty, cache = cache) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1497 | val log_store = Build_Log.store(options, cache = cache) | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1498 | val build_options = store.options | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1499 | |
| 79648 | 1500 | def main( | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1501 | server: SSH.Server, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1502 | database_server: Option[SQL.Database], | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1503 | log_database: PostgreSQL.Database, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1504 | host_database: SQL.Database | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1505 |     ): Schedule = {
 | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1506 | val full_sessions = | 
| 80056 | 1507 | Sessions.load_structure(build_options, dirs = AFP.main_dirs(afp_root) ::: dirs, | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1508 | select_dirs = select_dirs, infos = infos, augment_options = augment_options) | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1509 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1510 | val build_deps = | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1511 | Sessions.deps(full_sessions.selection(selection), progress = progress, | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1512 | inlined_files = true).check_errors | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1513 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1514 | val build_context = | 
| 79640 
7a2b86a48be0
prefer static object, while class is required for "services";
 wenzelm parents: 
79639diff
changeset | 1515 | Build.Context(store, build_deps, engine = Build_Engine, afp_root = afp_root, | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1516 | build_hosts = build_hosts, hostname = Build.hostname(build_options), | 
| 79644 | 1517 | numa_shuffling = numa_shuffling, session_setup = session_setup, master = true) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1518 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1519 | val cluster_hosts = build_context.build_hosts | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1520 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1521 | val hosts_current = | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1522 | cluster_hosts.forall(host => isabelle.Host.read_info(host_database, host.name).isDefined) | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1523 |       if (!hosts_current) {
 | 
| 79628 | 1524 | using(Build_Cluster.make(build_context, progress = progress).open())(_.init().benchmark()) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1525 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1526 | |
| 79926 
dc4a387a6f02
clarified host: pre-load max threads;
 Fabian Huch <huch@in.tum.de> parents: 
79925diff
changeset | 1527 | val host_infos = Host_Infos.load(build_options, cluster_hosts, host_database) | 
| 79877 
9aef1d1535ff
use timeout as default build time predictor if no data is available;
 Fabian Huch <huch@in.tum.de> parents: 
79871diff
changeset | 1528 | val timing_data = Timing_Data.load(host_infos, log_database, full_sessions) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1529 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1530 | val sessions = Build_Process.Sessions.empty.init(build_context, database_server, progress) | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1531 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1532 | val build_state = | 
| 79828 
5969ead9f900
clarified data representation: more uniform treatment of State.Pending vs. State.Running;
 wenzelm parents: 
79819diff
changeset | 1533 | Build_Process.State(sessions = sessions, | 
| 79829 | 1534 | pending = Map.from(sessions.iterator.map(Build_Process.Task.entry(_, build_context)))) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1535 | |
| 79640 
7a2b86a48be0
prefer static object, while class is required for "services";
 wenzelm parents: 
79639diff
changeset | 1536 | val scheduler = Build_Engine.scheduler(timing_data, build_context) | 
| 79105 | 1537 | def schedule_msg(res: Exn.Result[Schedule]): String = | 
| 1538 |         res match { case Exn.Res(schedule) => schedule.message case _ => "" }
 | |
| 1539 | ||
| 79594 | 1540 |       progress.echo("Building schedule...")
 | 
| 79592 
7db599be70cc
clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
 Fabian Huch <huch@in.tum.de> parents: 
79534diff
changeset | 1541 | Timing.timeit(scheduler.schedule(build_state), schedule_msg, output = progress.echo(_)) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1542 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1543 | |
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1544 |     using(store.open_server()) { server =>
 | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1545 |       using_optional(store.maybe_open_database_server(server = server)) { database_server =>
 | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1546 |         using(log_store.open_database(server = server)) { log_database =>
 | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1547 | using(store.open_build_database( | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1548 |             path = isabelle.Host.private_data.database, server = server)) { host_database =>
 | 
| 79648 | 1549 | main(server, database_server, log_database, host_database) | 
| 79091 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1550 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1551 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1552 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1553 | } | 
| 
06f380099b2e
added method to generate build schedules directly;
 Fabian Huch <huch@in.tum.de> parents: 
79090diff
changeset | 1554 | } | 
| 79181 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1555 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1556 |   def write_schedule_graphic(schedule: Schedule, output: Path): Unit = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1557 |     import java.awt.geom.{GeneralPath, Rectangle2D}
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1558 |     import java.awt.{BasicStroke, Color, Graphics2D}
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1559 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1560 | val line_height = isabelle.graphview.Metrics.default.height | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1561 | val char_width = isabelle.graphview.Metrics.default.char_width | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1562 | val padding = isabelle.graphview.Metrics.default.space_width | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1563 | val gap = isabelle.graphview.Metrics.default.gap | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1564 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1565 | val graph = schedule.graph | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1566 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1567 | def text_width(text: String): Double = text.length * char_width | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1568 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1569 | val generator_height = line_height + padding | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1570 | val hostname_height = generator_height + line_height + padding | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1571 | def time_height(time: Time): Double = time.seconds | 
| 79819 | 1572 | def date_height(date: Date): Double = time_height(date - schedule.start) | 
| 79181 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1573 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1574 | val hosts = graph.iterator.map(_._2._1).toList.groupBy(_.node_info.hostname) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1575 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1576 | def node_width(node: Schedule.Node): Double = 2 * padding + text_width(node.job_name) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1577 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1578 |     case class Range(start: Double, stop: Double) {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1579 | def proper: List[Range] = if (start < stop) List(this) else Nil | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1580 | def width: Double = stop - start | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1581 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1582 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1583 | val rel_node_ranges = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1584 |       hosts.toList.flatMap { (hostname, nodes) =>
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1585 | val sorted = nodes.sortBy(node => (node.start.time.ms, node.end.time.ms, node.job_name)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1586 |         sorted.foldLeft((List.empty[Schedule.Node], Map.empty[Schedule.Node, Range])) {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1587 | case ((nodes, allocated), node) => | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1588 | val width = node_width(node) + padding | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1589 | val parallel = nodes.filter(_.end.time > node.start.time) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1590 | val (last, slots) = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1591 |               parallel.sortBy(allocated(_).start).foldLeft((0D, List.empty[Range])) {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1592 | case ((start, ranges), node1) => | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1593 | val node_range = allocated(node1) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1594 | (node_range.stop, ranges ::: Range(start, node_range.start).proper) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1595 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1596 | val start = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1597 | (Range(last, Double.MaxValue) :: slots.filter(_.width >= width)).minBy(_.width).start | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1598 | (node :: parallel, allocated + (node -> Range(start, start + width))) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1599 | }._2 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1600 | }.toMap | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1601 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1602 | def host_width(hostname: String) = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1603 | 2 * padding + (hosts(hostname).map(rel_node_ranges(_).stop).max max text_width(hostname)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1604 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1605 | def graph_height(graph: Graph[String, Schedule.Node]): Double = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1606 | date_height(graph.maximals.map(graph.get_node(_).end).maxBy(_.unix_epoch)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1607 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1608 | val height = (hostname_height + 2 * padding + graph_height(graph)).ceil.toInt | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1609 | val (last, host_starts) = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1610 |       hosts.keys.foldLeft((0D, Map.empty[String, Double])) {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1611 | case ((previous, starts), hostname) => | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1612 | (previous + gap + host_width(hostname), starts + (hostname -> previous)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1613 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1614 | val width = (last - gap).ceil.toInt | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1615 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1616 | def node_start(node: Schedule.Node): Double = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1617 | host_starts(node.node_info.hostname) + padding + rel_node_ranges(node).start | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1618 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1619 |     def paint(gfx: Graphics2D): Unit = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1620 | gfx.setColor(Color.LIGHT_GRAY) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1621 | gfx.fillRect(0, 0, width, height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1622 | gfx.setRenderingHints(isabelle.graphview.Metrics.rendering_hints) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1623 | gfx.setFont(isabelle.graphview.Metrics.default.font) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1624 | gfx.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1625 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1626 | draw_string(schedule.generator + ", build time: " + schedule.duration.message_hms, padding, 0) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1627 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1628 |       def draw_host(x: Double, hostname: String): Double = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1629 | val nodes = hosts(hostname).map(_.job_name).toSet | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1630 | val width = host_width(hostname) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1631 | val height = 2 * padding + graph_height(graph.restrict(nodes.contains)) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1632 | val padding1 = ((width - text_width(hostname)) / 2) max 0 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1633 | val rect = new Rectangle2D.Double(x, hostname_height, width, height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1634 | gfx.setColor(Color.BLACK) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1635 | gfx.draw(rect) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1636 | gfx.setColor(Color.GRAY) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1637 | gfx.fill(rect) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1638 | draw_string(hostname, x + padding1, generator_height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1639 | x + gap + width | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1640 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1641 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1642 |       def draw_string(str: String, x: Double, y: Double): Unit = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1643 | gfx.setColor(Color.BLACK) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1644 | gfx.drawString(str, x.toInt, (y + line_height).toInt) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1645 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1646 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1647 |       def node_rect(node: Schedule.Node): Rectangle2D.Double = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1648 | val x = node_start(node) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1649 | val y = hostname_height + padding + date_height(node.start) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1650 | val width = node_width(node) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1651 | val height = time_height(node.duration) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1652 | new Rectangle2D.Double(x, y, width, height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1653 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1654 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1655 |       def draw_node(node: Schedule.Node): Rectangle2D.Double = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1656 | val rect = node_rect(node) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1657 | gfx.setColor(Color.BLACK) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1658 | gfx.draw(rect) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1659 | gfx.setColor(Color.WHITE) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1660 | gfx.fill(rect) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1661 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1662 | def add_text(y: Double, text: String): Double = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1663 | if (line_height > rect.height - y || text_width(text) + 2 * padding > rect.width) y | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1664 |           else {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1665 | val padding1 = padding min ((rect.height - (y + line_height)) / 2) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1666 | draw_string(text, rect.x + padding, rect.y + y + padding1) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1667 | y + padding1 + line_height | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1668 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1669 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1670 | val node_info = node.node_info | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1671 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1672 |         val duration_str = "(" + node.duration.message_hms + ")"
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1673 | val node_str = | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1674 |           "on " + proper_string(node_info.toString.stripPrefix(node_info.hostname)).getOrElse("all")
 | 
| 79819 | 1675 | val start_str = "Start: " + (node.start - schedule.start).message_hms | 
| 79181 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1676 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1677 | List(node.job_name, duration_str, node_str, start_str).foldLeft(0D)(add_text) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1678 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1679 | rect | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1680 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1681 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1682 |       def draw_arrow(from: Schedule.Node, to: Rectangle2D.Double, curve: Double = 10): Unit = {
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1683 | val from_rect = node_rect(from) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1684 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1685 | val path = new GeneralPath() | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1686 | path.moveTo(from_rect.getCenterX, from_rect.getMaxY) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1687 | path.lineTo(to.getCenterX, to.getMinY) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1688 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1689 | gfx.setColor(Color.BLUE) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1690 | gfx.draw(path) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1691 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1692 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1693 | hosts.keys.foldLeft(0D)(draw_host) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1694 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1695 |       graph.topological_order.foreach { job_name =>
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1696 | val node = graph.get_node(job_name) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1697 | val rect = draw_node(node) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1698 | |
| 79235 
d9f0eb441d74
improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79194diff
changeset | 1699 |         for {
 | 
| 
d9f0eb441d74
improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79194diff
changeset | 1700 | pred <- graph.imm_preds(job_name).iterator | 
| 
d9f0eb441d74
improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79194diff
changeset | 1701 | pred_node = graph.get_node(pred) | 
| 
d9f0eb441d74
improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79194diff
changeset | 1702 | if node.node_info.hostname != pred_node.node_info.hostname | 
| 
d9f0eb441d74
improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
 Fabian Huch <huch@in.tum.de> parents: 
79194diff
changeset | 1703 | } draw_arrow(pred_node, rect) | 
| 79181 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1704 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1705 | } | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1706 | |
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1707 | val name = output.file_name | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1708 | if (File.is_png(name)) Graphics_File.write_png(output.file, paint, width, height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1709 | else if (File.is_pdf(name)) Graphics_File.write_pdf(output.file, paint, width, height) | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1710 |     else error("Bad type of file: " + quote(name) + " (.png or .pdf expected)")
 | 
| 
9d6d559c9fde
added graphical representation of build schedules;
 Fabian Huch <huch@in.tum.de> parents: 
79180diff
changeset | 1711 | } | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1712 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1713 | |
| 79629 | 1714 | /* Isabelle tool wrapper */ | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1715 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1716 |   val isabelle_tool = Isabelle_Tool("build_schedule", "generate build schedule", Scala_Project.here,
 | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1717 |     { args =>
 | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1718 | var afp_root: Option[Path] = None | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1719 | val base_sessions = new mutable.ListBuffer[String] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1720 | val select_dirs = new mutable.ListBuffer[Path] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1721 | val build_hosts = new mutable.ListBuffer[Build_Cluster.Host] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1722 | var numa_shuffling = false | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1723 | var output_file: Option[Path] = None | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1724 | var requirements = false | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1725 | val exclude_session_groups = new mutable.ListBuffer[String] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1726 | var all_sessions = false | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1727 | val dirs = new mutable.ListBuffer[Path] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1728 | val session_groups = new mutable.ListBuffer[String] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1729 | var options = Options.init(specs = Options.Spec.ISABELLE_BUILD_OPTIONS) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1730 | var verbose = false | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1731 | val exclude_sessions = new mutable.ListBuffer[String] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1732 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1733 |       val getopts = Getopts("""
 | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1734 | Usage: isabelle build_schedule [OPTIONS] [SESSIONS ...] | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1735 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1736 | Options are: | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1737 |     -A ROOT      include AFP with given root directory (":" for """ + AFP.BASE.implode + """)
 | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1738 | -B NAME include session NAME and all descendants | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1739 | -D DIR include session directory and select its sessions | 
| 79615 | 1740 | -H HOSTS additional cluster host specifications of the form | 
| 1741 | NAMES:PARAMETERS (separated by commas) | |
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1742 | -N cyclic shuffling of NUMA CPU nodes (performance tuning) | 
| 79915 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1743 | -O FILE output file (pdf or png for image, else yxml) | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1744 | -R refer to requirements of selected sessions | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1745 | -X NAME exclude sessions from group NAME and all descendants | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1746 | -a select all sessions | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1747 | -d DIR include session directory | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1748 | -g NAME select session group NAME | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1749 | -o OPTION override Isabelle system OPTION (via NAME=VAL or NAME) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1750 | -v verbose | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1751 | -x NAME exclude session NAME and all descendants | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1752 | |
| 79909 | 1753 | Generate build schedule, but do not run actual build. | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1754 | """, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1755 | "A:" -> (arg => afp_root = Some(if (arg == ":") AFP.BASE else Path.explode(arg))), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1756 | "B:" -> (arg => base_sessions += arg), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1757 | "D:" -> (arg => select_dirs += Path.explode(arg)), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1758 | "H:" -> (arg => build_hosts ++= Build_Cluster.Host.parse(Registry.global, arg)), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1759 | "N" -> (_ => numa_shuffling = true), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1760 | "O:" -> (arg => output_file = Some(Path.explode(arg))), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1761 | "R" -> (_ => requirements = true), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1762 | "X:" -> (arg => exclude_session_groups += arg), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1763 | "a" -> (_ => all_sessions = true), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1764 | "d:" -> (arg => dirs += Path.explode(arg)), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1765 | "g:" -> (arg => session_groups += arg), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1766 | "o:" -> (arg => options = options + arg), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1767 | "v" -> (_ => verbose = true), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1768 | "x:" -> (arg => exclude_sessions += arg)) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1769 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1770 | val sessions = getopts(args) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1771 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1772 | val progress = new Console_Progress(verbose = verbose) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1773 | |
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1774 | val schedule = | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1775 | build_schedule(options, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1776 | selection = Sessions.Selection( | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1777 | requirements = requirements, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1778 | all_sessions = all_sessions, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1779 | base_sessions = base_sessions.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1780 | exclude_session_groups = exclude_session_groups.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1781 | exclude_sessions = exclude_sessions.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1782 | session_groups = session_groups.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1783 | sessions = sessions), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1784 | progress = progress, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1785 | afp_root = afp_root, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1786 | dirs = dirs.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1787 | select_dirs = select_dirs.toList, | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1788 | numa_shuffling = isabelle.Host.numa_check(progress, numa_shuffling), | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1789 | build_hosts = build_hosts.toList) | 
| 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1790 | |
| 79915 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1791 |       output_file match {
 | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1792 | case Some(output_file) if !schedule.is_empty => | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1793 | if (File.is_pdf(output_file.file_name) || File.is_png(output_file.file_name)) | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1794 | write_schedule_graphic(schedule, output_file) | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1795 | else Schedule.write(schedule, output_file) | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1796 | case _ => | 
| 
40d2f9ce29fc
allow read/write of schedule in build (read via option, write from tool);
 Fabian Huch <huch@in.tum.de> parents: 
79914diff
changeset | 1797 | } | 
| 79182 
6202d0ff36b4
added build schedule command-line wrapper;
 Fabian Huch <huch@in.tum.de> parents: 
79181diff
changeset | 1798 | }) | 
| 78845 
ff96d94957cb
add module for faster scheduled builds;
 Fabian Huch <huch@in.tum.de> parents: diff
changeset | 1799 | } |