src/Pure/Build/build_schedule.scala
author Fabian Huch <huch@in.tum.de>
Mon, 01 Jul 2024 18:22:33 +0200
changeset 80471 12901c03b416
parent 80274 cff00b3dddf5
child 80476 59e088605d49
permissions -rw-r--r--
remove inactive (e.g., crashed) hosts from scheduling;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
79502
c7a98469c0e7 clarified directories;
wenzelm
parents: 79294
diff changeset
     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
966aa081929f tuned imports;
wenzelm
parents: 78845
diff changeset
     9
import Host.Node_Info
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
    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: 79181
diff 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: 79909
diff 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
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    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: 79084
diff changeset
    20
    def elapsed: Time = timing.elapsed
79087
3620010c410a use cpu time for approximation;
Fabian Huch <huch@in.tum.de>
parents: 79086
diff 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: 79084
diff changeset
    22
  }
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    23
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    24
  object Timing_Data {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    25
    def median_timing(obs: List[Timing]): Timing = obs.sortBy(_.elapsed.ms).apply(obs.length / 2)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    26
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    27
    def median_time(obs: List[Time]): Time = obs.sortBy(_.ms).apply(obs.length / 2)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    28
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    29
    def mean_time(obs: Iterable[Time]): Time = Time.ms(obs.map(_.ms).sum / obs.size)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    30
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    31
    private def dummy_entries(host: Host, host_factor: Double) = {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    32
      val baseline = Time.minutes(5).scale(host_factor)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    33
      val gc = Time.seconds(10).scale(host_factor)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    34
      List(
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    35
        Result("dummy", host.name, 1, Timing(baseline, baseline, gc)),
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    36
        Result("dummy", host.name, 8, Timing(baseline.scale(0.2), baseline, gc)))
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    37
    }
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    38
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    39
    def make(
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    40
      host_infos: Host_Infos,
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    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: 79871
diff changeset
    42
      session_structure: Sessions.Structure,
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    43
    ): Timing_Data = {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    44
      val hosts = host_infos.hosts
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    45
      val measurements =
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    46
        for {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    47
          (meta_info, build_info) <- build_history
79818
0c2a62a9f136 more operations for Build_Log.Meta_Info: prefer explicit types;
wenzelm
parents: 79805
diff changeset
    48
          build_host = meta_info.get_build_host
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    49
          (job_name, session_info) <- build_info.sessions.toList
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    50
          if build_info.finished_sessions.contains(job_name)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    51
          hostname <- session_info.hostname.orElse(build_host).toList
79880
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff 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: 79926
diff changeset
    53
          threads = session_info.threads.getOrElse(host.max_threads)
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    54
        } yield (job_name, hostname, threads) -> session_info.timing
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    55
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    56
      val entries =
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    57
        if (measurements.isEmpty) {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    58
          val default_host = host_infos.hosts.sorted(host_infos.host_speeds).last
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    59
          host_infos.hosts.flatMap(host =>
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    60
            dummy_entries(host, host_infos.host_factor(default_host, host)))
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    61
        }
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    62
        else
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    63
          measurements.groupMap(_._1)(_._2).toList.map {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    64
            case ((job_name, hostname, threads), timings) =>
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    65
              Result(job_name, hostname, threads, median_timing(timings))
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    66
          }
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    67
79877
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff changeset
    68
      new Timing_Data(new Facet(entries), host_infos, session_structure)
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    69
    }
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    70
79877
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff changeset
    71
    def load(
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff 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: 79871
diff 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: 79871
diff 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: 79871
diff changeset
    75
    ): Timing_Data = {
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    76
      val build_history =
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    77
        for {
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    78
          log_name <- log_database.execute_query_statement(
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    79
            Build_Log.private_data.meta_info_table.select(List(Build_Log.Column.log_name)),
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    80
            List.from[String], res => res.string(Build_Log.Column.log_name))
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    81
          meta_info <- Build_Log.private_data.read_meta_info(log_database, log_name)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    82
          build_info = Build_Log.private_data.read_build_info(log_database, log_name)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    83
        } yield (meta_info, build_info)
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    84
79877
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff changeset
    85
      make(host_infos, build_history, sessions_structure)
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
    86
    }
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    87
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 80274
diff 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: 80274
diff 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: 80274
diff 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: 80274
diff changeset
    92
    }
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
    93
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    94
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    95
    /* data facets */
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    96
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    97
    object Facet {
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    98
      def unapply(facet: Facet): Option[List[Result]] = Some(facet.results)
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
    99
    }
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   100
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   101
    class Facet private[Timing_Data](val results: List[Result]) {
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   102
      require(results.nonEmpty)
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   103
79649
981cd49a3f90 more explicit types --- fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79648
diff changeset
   104
      def is_empty: Boolean = results.isEmpty
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   105
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   106
      def size: Int = results.length
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   107
79649
981cd49a3f90 more explicit types --- fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79648
diff 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: 79648
diff 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: 79648
diff changeset
   110
      lazy val by_hostname: Map[String, Facet] = results.groupBy(_.hostname).view.mapValues(new Facet(_)).toMap
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   111
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   112
      def median_time: Time = Timing_Data.median_time(results.map(_.elapsed))
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   113
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   114
      def best_result: Result = results.minBy(_.elapsed.ms)
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   115
    }
79189
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
   116
  }
Fabian Huch <huch@in.tum.de>
parents: 79188
diff changeset
   117
79877
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff changeset
   118
  class Timing_Data private(
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 79871
diff 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: 79871
diff 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: 79871
diff changeset
   122
  ) {
79025
f78ee2d48bf5 handle inflection point in interpolation with monotone prefix;
Fabian Huch <huch@in.tum.de>
parents: 79024
diff 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: 79024
diff changeset
   124
      last_mono + ((next - last_mono) / 2)
f78ee2d48bf5 handle inflection point in interpolation with monotone prefix;
Fabian Huch <huch@in.tum.de>
parents: 79024
diff changeset
   125
79028
6bada416ba55 clarified timing data operations: proper estimation (instead of known points);
Fabian Huch <huch@in.tum.de>
parents: 79027
diff 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: 79027
diff changeset
   127
      val worse_threads =
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   128
        facet.by_job.get(job_name).toList.flatMap(_.by_hostname).flatMap {
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   129
          case (hostname, facet) =>
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   130
            val best_threads = facet.best_result.threads
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   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: 79027
diff changeset
   132
              inflection_point(best_threads, _))
6bada416ba55 clarified timing data operations: proper estimation (instead of known points);
Fabian Huch <huch@in.tum.de>
parents: 79027
diff changeset
   133
        }
6bada416ba55 clarified timing data operations: proper estimation (instead of known points);
Fabian Huch <huch@in.tum.de>
parents: 79027
diff 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: 79027
diff 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
ff7d48e776ab properly sort entries;
Fabian Huch <huch@in.tum.de>
parents: 79040
diff changeset
   140
    private def approximate_threads(entries_unsorted: List[(Int, Time)], threads: Int): Time = {
ff7d48e776ab properly sort entries;
Fabian Huch <huch@in.tum.de>
parents: 79040
diff changeset
   141
      val entries = entries_unsorted.sortBy(_._1)
ff7d48e776ab properly sort entries;
Fabian Huch <huch@in.tum.de>
parents: 79040
diff changeset
   142
79036
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   144
        xs match {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   145
          case x1 :: x2 :: xs =>
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   147
          case xs => xs
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   148
        }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   149
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff 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: 79035
diff changeset
   152
        val b = p0._2 - a.scale(p0._1)
79184
Fabian Huch <huch@in.tum.de>
parents: 79183
diff changeset
   153
        (a.scale(threads) + b) max Time.zero
79036
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   154
      }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   155
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   157
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   158
      val is_mono = entries == mono_prefix
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   160
      val in_inflection =
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   162
      if (is_mono || in_prefix || in_inflection) {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   163
        // Model with Amdahl's law
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   164
        val t_p =
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   165
          Timing_Data.median_time(for {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   166
            (n, t0) <- mono_prefix
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   167
            (m, t1) <- mono_prefix
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   168
            if m != n
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   170
        val t_c =
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   172
79184
Fabian Huch <huch@in.tum.de>
parents: 79183
diff changeset
   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: 79035
diff changeset
   174
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   175
        if (is_mono || in_prefix) model(threads)
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   176
        else {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff 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: 79035
diff changeset
   179
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   180
          if (threads <= inflection_threads) model(threads)
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   182
        }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   183
      } else {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   184
        // Piecewise linear
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   185
        val (p0, p1) =
79042
1a9f3806987d proper split;
Fabian Huch <huch@in.tum.de>
parents: 79041
diff changeset
   186
          if (entries.head._1 < threads && threads < entries.last._1) {
1a9f3806987d proper split;
Fabian Huch <huch@in.tum.de>
parents: 79041
diff changeset
   187
            val split = entries.partition(_._1 < threads)
79036
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   188
            (split._1.last, split._2.head)
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   189
          } else {
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff 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: 79035
diff changeset
   191
            (piece.head, piece.last)
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   192
          }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   193
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   194
        linear(p0, p1)
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   195
      }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   196
    }
be42ba4b4672 split actual approximation from data handling;
Fabian Huch <huch@in.tum.de>
parents: 79035
diff changeset
   197
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   198
    private def unify_hosts(job_name: String, on_host: String): List[(Int, Time)] = {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   199
      def unify(hostname: String, facet: Timing_Data.Facet) =
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   200
        facet.median_time.scale(hostname_factor(hostname, on_host))
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   201
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   202
      for {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   203
        facet <- facet.by_job.get(job_name).toList
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   204
        (threads, facet) <- facet.by_threads
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   205
        entries = facet.by_hostname.toList.map(unify)
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   206
      } yield threads -> Timing_Data.mean_time(entries)
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   207
    }
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   208
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   209
    def estimate_threads(job_name: String, hostname: String, threads: Int): Option[Time] = {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   210
      def try_approximate(facet: Timing_Data.Facet): Option[Time] = {
79087
3620010c410a use cpu time for approximation;
Fabian Huch <huch@in.tum.de>
parents: 79086
diff changeset
   211
        val entries =
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   212
          facet.by_threads.toList match {
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   213
            case List((i, Timing_Data.Facet(List(result)))) if i != 1 =>
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   214
              (i, facet.median_time) :: result.proper_cpu.map(1 -> _).toList
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   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: 79086
diff changeset
   216
          }
3620010c410a use cpu time for approximation;
Fabian Huch <huch@in.tum.de>
parents: 79086
diff 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: 79086
diff changeset
   218
      }
3620010c410a use cpu time for approximation;
Fabian Huch <huch@in.tum.de>
parents: 79086
diff changeset
   219
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   220
      for {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   221
        facet <- facet.by_job.get(job_name)
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   222
        facet <- facet.by_hostname.get(hostname)
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   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: 79036
diff changeset
   224
      } yield time
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   225
    }
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   226
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   227
    def global_threads_factor(from: Int, to: Int): Double = {
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff 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: 79035
diff changeset
   229
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   230
      val estimates =
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   231
        for {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   232
          (hostname, facet) <- facet.by_hostname
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   233
          job_name <- facet.by_job.keys
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   234
          from_time <- estimate_threads(job_name, hostname, from)
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   235
          to_time <- estimate_threads(job_name, hostname, to)
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff 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: 79036
diff changeset
   238
      if (estimates.nonEmpty) median(estimates)
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   239
      else {
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   240
        // unify hosts
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   241
        val estimates =
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   242
          for {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   243
            (job_name, facet) <- facet.by_job
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   244
            hostname = facet.by_hostname.keys.head
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   245
            entries = unify_hosts(job_name, hostname)
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   246
            if entries.length > 1
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   247
          } yield
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff 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: 79036
diff changeset
   250
        if (estimates.nonEmpty) median(estimates)
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   251
        else from.toDouble / to.toDouble
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff 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: 79110
diff changeset
   255
    private var cache: Map[(String, String, Int), Time] = Map.empty
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   256
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   257
79534
1dcc97227442 add approximation factors in build schedule to estimate build times more conservatively;
Fabian Huch <huch@in.tum.de>
parents: 79527
diff changeset
   258
    /* approximation factors -- penalize estimations with less information */
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   259
79534
1dcc97227442 add approximation factors in build schedule to estimate build times more conservatively;
Fabian Huch <huch@in.tum.de>
parents: 79527
diff 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: 79527
diff 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: 79527
diff 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: 79527
diff 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: 79527
diff 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: 79527
diff changeset
   265
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   266
    def estimate(job_name: String, hostname: String, threads: Int): Time = {
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   267
      def estimate: Time =
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   268
        facet.by_job.get(job_name) match {
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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: 79871
diff 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: 79892
diff 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: 79871
diff 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: 79871
diff 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: 79871
diff changeset
   274
              default_time
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff 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: 79871
diff 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: 79871
diff changeset
   277
            }
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   278
            else {
79877
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff 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: 79871
diff 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: 79871
diff 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: 79871
diff changeset
   282
              else {
9aef1d1535ff use timeout as default build time predictor if no data is available;
Fabian Huch <huch@in.tum.de>
parents: 79871
diff 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: 79871
diff changeset
   284
                val (threads1, facet1) = facet.by_threads.head
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   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: 79871
diff changeset
   286
              }
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   287
            }
79038
cd7c1acc9cf2 better estimation for unknown jobs;
Fabian Huch <huch@in.tum.de>
parents: 79037
diff changeset
   288
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   289
          case Some(facet) =>
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   290
            facet.by_threads.get(threads) match {
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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: 79527
diff 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: 79527
diff changeset
   293
                  FACTOR_NO_THREADS_SAME_MACHINE)).getOrElse {
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   294
                  // per machine, try to approximate config for threads
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   295
                  val approximated =
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   296
                    for {
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   297
                      hostname1 <- facet.by_hostname.keys
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   298
                      estimate <- estimate_threads(job_name, hostname1, threads)
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   299
                      factor = hostname_factor(hostname1, hostname)
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   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: 79527
diff 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: 79110
diff changeset
   304
                  else {
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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: 79110
diff changeset
   306
                    val unified_entries = unify_hosts(job_name, hostname)
79037
1b3a6cc4a2bf clarified and tuned timing estimation;
Fabian Huch <huch@in.tum.de>
parents: 79036
diff changeset
   307
79534
1dcc97227442 add approximation factors in build schedule to estimate build times more conservatively;
Fabian Huch <huch@in.tum.de>
parents: 79527
diff 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: 79527
diff 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: 79527
diff changeset
   310
                        FACTOR_NO_THREADS_UNIFY_MACHINES)
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   311
                    else {
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   312
                      // only single data point, use global curve to approximate
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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: 79527
diff 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: 79527
diff changeset
   315
                        FACTOR_NO_THREADS_GLOBAL_CURVE)
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   320
              case Some(facet) => // time for job/thread exists, interpolate machine if necessary
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   321
                facet.by_hostname.get(hostname).map(_.median_time).getOrElse {
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   322
                  Timing_Data.mean_time(
79593
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   323
                    facet.by_hostname.toList.map((hostname1, facet) =>
79913
82bddaf3bd33 proper median/mean time;
Fabian Huch <huch@in.tum.de>
parents: 79912
diff changeset
   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: 79527
diff changeset
   325
                    FACTOR_THREADS_OTHER_MACHINE)
79178
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   326
                }
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   327
            }
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   328
        }
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   329
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   330
      cache.get(job_name, hostname, threads) match {
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   331
        case Some(time) => time
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   332
        case None =>
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   333
          val time = estimate
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff changeset
   334
          cache = cache + ((job_name, hostname, threads) -> time)
96e5d12c82fd performance tuning: cache estimates;
Fabian Huch <huch@in.tum.de>
parents: 79110
diff 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: 79110
diff 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
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   343
  object Host {
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   344
    def load(options: Options, build_host: Build_Cluster.Host, host_db: SQL.Database): Host = {
79925
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   345
      val name = build_host.name
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   346
      val info =
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   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: 79925
diff changeset
   348
      val max_threads = (options ++ build_host.options).threads(default = info.num_cpus)
79925
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   349
      val score = info.benchmark_score.getOrElse(error("No benchmark for " + quote(name)))
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   350
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   351
      Host(
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   352
        name = name,
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   353
        num_cpus = info.num_cpus,
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   354
        max_jobs = build_host.jobs,
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   355
        max_threads = max_threads,
79925
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   356
        numa = build_host.numa,
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   357
        numa_nodes = info.numa_nodes,
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   358
        benchmark_score = score,
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   359
        options = build_host.options)
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   360
    }
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   361
  }
26b571c90808 clarified: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79921
diff changeset
   362
79880
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   363
  case class Host(
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   364
    name: String,
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   365
    num_cpus: Int,
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   366
    max_jobs: Int,
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   367
    max_threads: Int,
79880
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   368
    benchmark_score: Double,
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   369
    numa: Boolean = false,
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   370
    numa_nodes: List[Int] = Nil,
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff 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: 79925
diff changeset
   374
    def load(
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   375
      options: Options,
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   376
      build_hosts: List[Build_Cluster.Host],
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
   377
      host_db: SQL.Database
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff 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: 80274
diff changeset
   381
  case class Host_Infos(hosts: List[Host]) {
79040
Fabian Huch <huch@in.tum.de>
parents: 79039
diff changeset
   382
    require(hosts.nonEmpty)
Fabian Huch <huch@in.tum.de>
parents: 79039
diff changeset
   383
79103
883f61f0beda clarified build schedule host: more operations;
Fabian Huch <huch@in.tum.de>
parents: 79102
diff 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: 79879
diff 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
dd689c4ab688 consistent hosts ordering;
Fabian Huch <huch@in.tum.de>
parents: 79083
diff changeset
   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: 79926
diff 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
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   402
        state.running.values.map(_.node_info).groupMapReduce(_.hostname)(List(_))(_ ::: _)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   408
  /* offline tracking of job configurations and resource allocations */
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   409
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   410
  case class Config(job_name: String, node_info: Node_Info) {
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   411
    def job_of(start_time: Time): Build_Process.Job =
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   412
      Build_Process.Job(job_name, "", "", node_info, Date(start_time), None)
Fabian Huch <huch@in.tum.de>
parents: 79028
diff changeset
   413
  }
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   414
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   415
  class Resources(
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   416
    val host_infos: Host_Infos,
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   419
    def unused_nodes(host: Host, threads: Int): List[Node_Info] =
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   420
      if (!available(host, threads)) Nil
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   421
      else {
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   422
        val node = next_node(host, threads)
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   423
        node :: allocate(node).unused_nodes(host, threads)
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   424
      }
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   425
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   426
    def unused_nodes(threads: Int): List[Node_Info] =
91955d607aad proper unused nodes;
Fabian Huch <huch@in.tum.de>
parents: 79105
diff changeset
   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
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   431
    def allocate(node_info: Node_Info): Resources = {
587a7dfeb03c clarified names;
Fabian Huch <huch@in.tum.de>
parents: 79592
diff changeset
   432
      val host = host_infos.the_host(node_info)
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 78970
diff changeset
   437
      hosts: List[(Host, Int)],
f930d24f1548 scheduled build: allocate cpus more aggressively, to avoid idle threads;
Fabian Huch <huch@in.tum.de>
parents: 78970
diff 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: 78970
diff 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: 78970
diff 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: 78970
diff 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: 79926
diff 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: 78970
diff 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: 79879
diff 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: 79879
diff 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: 79879
diff 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: 79102
diff 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: 79879
diff 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: 80056
diff 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: 79926
diff 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: 80056
diff 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: 79879
diff changeset
   487
          host.numa_nodes.exists(
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff 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: 79064
diff changeset
   497
  object Schedule {
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79064
diff 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: 79064
diff changeset
   500
    }
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   501
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   502
    type Graph = isabelle.Graph[String, Node]
79183
32d00ec387f4 use schedule directly instead of extra cache;
Fabian Huch <huch@in.tum.de>
parents: 79182
diff changeset
   503
79185
cfed4fcf1dae add build uuid to schedule;
Fabian Huch <huch@in.tum.de>
parents: 79184
diff changeset
   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: 79913
diff changeset
   505
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   506
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   507
    /* file representation */
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   508
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff changeset
   510
      import XML.Encode._
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   511
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79915
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff changeset
   521
        (schedule =>
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff 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: 79913
diff changeset
   524
            schedule.serial))))))
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   525
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff changeset
   527
    }
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   528
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff changeset
   530
      import XML.Decode._
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   531
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79915
diff 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: 79913
diff 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: 79913
diff changeset
   535
        { body =>
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff 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: 79913
diff changeset
   538
        }
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff changeset
   540
        { body =>
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff changeset
   544
        }
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff changeset
   546
        { body =>
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff 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: 79913
diff 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: 79913
diff 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: 79913
diff changeset
   550
        }
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   551
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   552
      schedule(YXML.parse_body(File.read(file)))
9da3019e1ee5 file representation for schedule (e.g., for generating from external tool);
Fabian Huch <huch@in.tum.de>
parents: 79913
diff changeset
   553
    }
79073
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   554
  }
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   555
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   556
  case class Schedule(
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   557
    build_uuid: String,
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   558
    generator: String,
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   559
    start: Date,
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   560
    graph: Schedule.Graph,
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   561
    serial: Long = 0,
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
   562
  ) {
79835
866d96915388 clarified modules;
wenzelm
parents: 79834
diff changeset
   563
    def next_serial: Long = Build_Process.State.inc_serial(serial)
866d96915388 clarified modules;
wenzelm
parents: 79834
diff changeset
   564
79073
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   565
    def end: Date =
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   566
      if (graph.is_empty) start
79897
Fabian Huch <huch@in.tum.de>
parents: 79896
diff changeset
   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: 79064
diff changeset
   568
79819
wenzelm
parents: 79818
diff changeset
   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: 79909
diff 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: 79108
diff 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: 79182
diff changeset
   572
79819
wenzelm
parents: 79818
diff changeset
   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: 79191
diff 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: 79191
diff 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: 79191
diff changeset
   576
    def elapsed(): Time = Time.now() - start.time
79293
1f694e4b2b3a clarified signature;
Fabian Huch <huch@in.tum.de>
parents: 79292
diff changeset
   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: 79288
diff changeset
   578
    def is_outdated(options: Options, state: Build_Process.State): Boolean =
79293
1f694e4b2b3a clarified signature;
Fabian Huch <huch@in.tum.de>
parents: 79292
diff changeset
   579
      if (is_empty) true
79912
fe96a842f065 remove schedule outdated limit: delay is sufficient;
Fabian Huch <huch@in.tum.de>
parents: 79911
diff 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: 79182
diff changeset
   581
79921
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79935
diff changeset
   583
      val now = Time.now()
05e034a54924 only start jobs early if they are due (cf. 1966578feff8);
Fabian Huch <huch@in.tum.de>
parents: 79935
diff changeset
   584
79921
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   585
      val next_nodes =
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   586
        for {
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79928
diff changeset
   588
          if graph.defined(task.name)
79921
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   589
          node = graph.get_node(task.name)
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   590
          if hostname == node.node_info.hostname
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   591
        } yield node
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   592
79946
05e034a54924 only start jobs early if they are due (cf. 1966578feff8);
Fabian Huch <huch@in.tum.de>
parents: 79935
diff changeset
   593
      val (ready, other) =
79921
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79935
diff changeset
   595
05e034a54924 only start jobs early if they are due (cf. 1966578feff8);
Fabian Huch <huch@in.tum.de>
parents: 79935
diff changeset
   596
      val waiting = other.filter(_.start.time <= now)
79921
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79916
diff changeset
   598
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79916
diff changeset
   600
        val existing = ready.map(_.node_info) ::: running
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff 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: 79916
diff 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: 79916
diff changeset
   603
      }
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   604
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   605
      waiting.foldLeft(ready)(try_run).map(_.job_name)
1966578feff8 start scheduled jobs earlier, if possible;
Fabian Huch <huch@in.tum.de>
parents: 79916
diff changeset
   606
    }
79193
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff 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: 79909
diff 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: 79895
diff changeset
   609
      next(hostname, state).nonEmpty
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
   610
79193
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff 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: 79192
diff changeset
   612
      val start1 = Date.now()
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff changeset
   613
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff 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: 79192
diff changeset
   615
        graph.map_node(name, { node =>
79819
wenzelm
parents: 79818
diff changeset
   616
          val elapsed = start1 - state.running(name).start_date
79897
Fabian Huch <huch@in.tum.de>
parents: 79896
diff changeset
   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: 79192
diff changeset
   618
        })
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff changeset
   619
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff 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: 79192
diff 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: 79192
diff 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: 79192
diff 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: 79192
diff changeset
   624
        })
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff changeset
   625
79828
5969ead9f900 clarified data representation: more uniform treatment of State.Pending vs. State.Running;
wenzelm
parents: 79819
diff changeset
   626
      val graph0 =
5969ead9f900 clarified data representation: more uniform treatment of State.Pending vs. State.Running;
wenzelm
parents: 79819
diff 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: 79192
diff 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: 79192
diff changeset
   629
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff 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: 79192
diff changeset
   631
    }
79073
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   632
  }
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff changeset
   633
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79025
diff 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: 79025
diff 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: 79064
diff changeset
   653
        val now = current_time + elapsed
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79064
diff 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: 79190
diff 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: 79190
diff changeset
   657
          for {
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   658
            name <- finished.graph.keys
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   659
            pred_node = finished.graph.get_node(name)
79236
6dc4fd89987f filter predecessors properly (amending ee405c40db72);
Fabian Huch <huch@in.tum.de>
parents: 79235
diff 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: 79235
diff 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: 79190
diff 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: 79190
diff changeset
   663
        val build_preds =
79073
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79190
diff 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: 79190
diff 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: 79190
diff 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: 79064
diff changeset
   668
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79064
diff 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: 79064
diff 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: 79534
diff 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: 79534
diff changeset
   678
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 78930
diff changeset
   680
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   685
  ) extends Scheduler {
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79064
diff 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: 79534
diff changeset
   691
          val state1 =
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   692
            priority_rule
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79064
diff 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: 79534
diff changeset
   700
      val name = "generation scheme (" + priority_rule + ")"
79109
c1255d9870f6 clarified heuristics toString;
Fabian Huch <huch@in.tum.de>
parents: 79108
diff 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: 79534
diff 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: 79064
diff changeset
   703
b3fee0dafd72 generated build schedule explicitly (e.g., for further analysis);
Fabian Huch <huch@in.tum.de>
parents: 79064
diff 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: 79927
diff 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: 79534
diff 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: 79534
diff changeset
   710
79805
45198ea3f0b3 parallelize schedule optimization;
Fabian Huch <huch@in.tum.de>
parents: 79785
diff changeset
   711
    def schedule(state: Build_Process.State): Schedule = {
45198ea3f0b3 parallelize schedule optimization;
Fabian Huch <huch@in.tum.de>
parents: 79785
diff changeset
   712
      def main(scheduler: Scheduler): Schedule = scheduler.schedule(state)
79928
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff 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: 79927
diff changeset
   714
        schedule.durations.map(_.ms).sorted.reverse)
79805
45198ea3f0b3 parallelize schedule optimization;
Fabian Huch <huch@in.tum.de>
parents: 79785
diff changeset
   715
    }
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   716
  }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   717
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   718
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   719
  /* priority rules */
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   720
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff 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: 79534
diff 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: 79106
diff changeset
   723
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff 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: 79925
diff 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: 79106
diff changeset
   726
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79106
diff 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: 79106
diff changeset
   729
      val resources = host_infos.available(state)
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff changeset
   730
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff 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: 79106
diff changeset
   732
        case ((jobs, res), host) =>
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff 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: 79106
diff 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: 79106
diff 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: 79106
diff changeset
   736
      }._2
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff changeset
   737
    }
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff changeset
   738
  }
f5a2f956b531 add heuristic for non-scheduled (standard) build behaviour;
Fabian Huch <huch@in.tum.de>
parents: 79106
diff changeset
   739
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   744
    }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   747
    }
78931
26841d3c568c performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
Fabian Huch <huch@in.tum.de>
parents: 78930
diff changeset
   748
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   752
    }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   755
    }
78931
26841d3c568c performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
Fabian Huch <huch@in.tum.de>
parents: 78930
diff changeset
   756
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   760
    }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   763
    }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   766
    }
78931
26841d3c568c performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
Fabian Huch <huch@in.tum.de>
parents: 78930
diff changeset
   767
  }
26841d3c568c performance tuning for build schedule: explicit schedule generation, without mixing heuristics;
Fabian Huch <huch@in.tum.de>
parents: 78930
diff changeset
   768
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79026
diff changeset
   773
    timing_data: Timing_Data,
d08fb157e300 use proper max threads (limited by available hardware) in heuristics;
Fabian Huch <huch@in.tum.de>
parents: 79026
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   778
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff changeset
   780
      val params =
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   781
        List(
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff 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: 79534
diff changeset
   786
    }
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
   787
78929
df323f23dfde performance tuning for timing heuristic: pre-calculate graph operations;
Fabian Huch <huch@in.tum.de>
parents: 78928
diff changeset
   788
    /* pre-computed properties for efficient heuristic */
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   789
    val host_infos: Host_Infos = timing_data.host_infos
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff 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: 78928
diff changeset
   791
79927
4359257218ce clarify use of num_threads vs. max_cpus;
Fabian Huch <huch@in.tum.de>
parents: 79926
diff changeset
   792
    val max_threads: Int = host_infos.hosts.map(_.max_threads).max min max_threads_limit
79102
4d5f878665a3 clarified path heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79101
diff changeset
   793
78929
df323f23dfde performance tuning for timing heuristic: pre-calculate graph operations;
Fabian Huch <huch@in.tum.de>
parents: 78928
diff changeset
   794
    type Node = String
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff 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: 79091
diff changeset
   796
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   797
    val minimals: List[Node] = build_graph.minimals
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   798
    val maximals: List[Node] = build_graph.maximals
79101
4e47b34fbb8e clarified graph operations in timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79091
diff changeset
   799
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   800
    val best_threads: Map[Node, Int] =
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   801
      build_graph.keys.map(node => node -> timing_data.best_threads(node, max_threads)).toMap
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   802
79102
4d5f878665a3 clarified path heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79101
diff changeset
   803
    def best_time(node: Node): Time = {
4d5f878665a3 clarified path heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79101
diff changeset
   804
      val host = ordered_hosts.last
79927
4359257218ce clarify use of num_threads vs. max_cpus;
Fabian Huch <huch@in.tum.de>
parents: 79926
diff 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: 79102
diff changeset
   806
      timing_data.estimate(node, host.name, threads)
79102
4d5f878665a3 clarified path heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79101
diff changeset
   807
    }
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff 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: 78928
diff changeset
   809
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff 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: 79091
diff 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: 79091
diff 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: 78928
diff changeset
   813
79101
4e47b34fbb8e clarified graph operations in timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79091
diff 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: 79091
diff 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: 79091
diff 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: 79091
diff 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: 78928
diff changeset
   818
    }
df323f23dfde performance tuning for timing heuristic: pre-calculate graph operations;
Fabian Huch <huch@in.tum.de>
parents: 78928
diff changeset
   819
79101
4e47b34fbb8e clarified graph operations in timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79091
diff 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: 79091
diff 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: 79091
diff changeset
   822
79713
d3a26436e679 tuned signature: more types, fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79703
diff changeset
   823
    val node_degrees: Map[Node, Int] =
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 78971
diff changeset
   825
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   826
    def parallel_paths(
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   827
      running: List[(Node, Time)],
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   828
      nodes: Set[Node] = build_graph.keys.toSet,
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   829
      max: Int = Int.MaxValue
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   830
    ): Int =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   831
      if (nodes.nonEmpty && nodes.map(node_degrees.apply).max > max) max
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   832
      else {
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   833
        def start(node: Node): (Node, Time) = node -> best_times(node)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   834
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   835
        def pass_time(elapsed: Time)(node: Node, time: Time): (Node, Time) =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   836
          node -> (time - elapsed)
78972
7a39f151e9a7 proper parallel paths for timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 78971
diff changeset
   837
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   838
        def parallel_paths(running: Map[Node, Time]): (Int, Map[Node, Time]) =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   839
          if (running.size >= max) (max, running)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   840
          else if (running.isEmpty) (0, running)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   841
          else {
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   842
            def get_next(node: Node): List[Node] =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   843
              build_graph.imm_succs(node).intersect(nodes).filter(
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 78971
diff changeset
   845
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   846
            val (next, elapsed) = running.minBy(_._2.ms)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   847
            val (remaining, finished) =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 78971
diff changeset
   849
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   850
            val running1 =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   851
              remaining.map(pass_time(elapsed)).toMap ++
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   852
                finished.map(_._1).flatMap(get_next).map(start)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   853
            val (res, running2) = parallel_paths(running1)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   854
            (res max running.size, running2)
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   855
          }
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   856
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   857
        parallel_paths(running.toMap)._1
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   858
      }
78929
df323f23dfde performance tuning for timing heuristic: pre-calculate graph operations;
Fabian Huch <huch@in.tum.de>
parents: 78928
diff changeset
   859
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff 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
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 78970
diff changeset
   864
79028
6bada416ba55 clarified timing data operations: proper estimation (instead of known points);
Fabian Huch <huch@in.tum.de>
parents: 79027
diff 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: 79179
diff changeset
   867
      val available_nodes =
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   868
        host_infos.available(state.copy(running = Map.empty))
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   869
          .unused_nodes(max_threads)
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff 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: 79178
diff changeset
   871
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   872
      def remaining_time(node: Node): (Node, Time) =
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   873
        state.running.get(node) match {
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   874
          case None => node -> best_times(node)
79179
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   875
          case Some(job) =>
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   876
            val estimate =
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff 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: 79178
diff changeset
   878
                host_infos.num_threads(job.node_info))
79184
Fabian Huch <huch@in.tum.de>
parents: 79183
diff changeset
   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: 79178
diff changeset
   880
        }
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   881
79101
4e47b34fbb8e clarified graph operations in timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79091
diff changeset
   882
      val next_sorted = state.next_ready.sortBy(max_time(_).ms).reverse
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   883
      val is_parallelizable =
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   884
        available_nodes.length >= parallel_paths(
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   885
          state.ready.map(_.name).map(remaining_time),
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   886
          max = available_nodes.length + 1)
79088
32e839bb622e tuned heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79087
diff changeset
   887
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   888
      if (is_parallelizable) {
79101
4e47b34fbb8e clarified graph operations in timing heuristic;
Fabian Huch <huch@in.tum.de>
parents: 79091
diff 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: 79027
diff 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: 78970
diff 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: 79109
diff 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: 79109
diff changeset
   894
          this.is_critical match {
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff 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: 79109
diff 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: 79109
diff changeset
   897
          }
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
   898
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff 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: 79109
diff changeset
   900
        val critical_nodes =
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff 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: 79091
diff 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: 78970
diff 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: 79109
diff changeset
   906
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff 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: 79109
diff changeset
   908
          this.parallel_threads match {
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
   909
            case Fixed_Thread(threads) => threads
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   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: 79109
diff changeset
   911
          }
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
   912
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff 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: 78970
diff changeset
   914
79179
7ed43417770f proper parallel paths: factor in elapsed time;
Fabian Huch <huch@in.tum.de>
parents: 79178
diff changeset
   915
        val max_critical_parallel =
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
   916
          parallel_paths(critical_minimals.map(remaining_time), critical_nodes)
79180
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   917
        val max_critical_hosts =
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   918
          available_nodes.take(max_critical_parallel).map(_.hostname).distinct.length
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   919
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   920
        val split =
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   921
          this.host_criterion match {
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   922
            case Critical_Nodes => max_critical_hosts
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   923
            case Fixed_Fraction(fraction) =>
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff 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: 79179
diff changeset
   925
            case Host_Speed(min_factor) =>
79880
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff changeset
   926
              val best = rev_ordered_hosts.head._1.benchmark_score
79180
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   927
              val num_fast =
79880
a3d53f2bc41d clarified build schedule host: proper module;
Fabian Huch <huch@in.tum.de>
parents: 79879
diff 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: 79179
diff changeset
   929
              num_fast min max_critical_hosts
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   930
          }
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
   931
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff 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: 78970
diff 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: 78970
diff 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: 79289
diff 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: 79289
diff 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: 79185
diff 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: 79185
diff changeset
   951
79649
981cd49a3f90 more explicit types --- fewer warnings in IntelliJ IDEA;
wenzelm
parents: 79648
diff 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: 79185
diff 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: 79185
diff 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: 79502
diff 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: 79185
diff 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: 79185
diff 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: 79185
diff changeset
   958
          case Some(db) =>
79761
wenzelm
parents: 79713
diff changeset
   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: 79867
diff changeset
   960
              val old_state =
79904
1cfc913987d9 clarified names;
wenzelm
parents: 79898
diff changeset
   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: 79185
diff 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: 79502
diff 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: 79185
diff 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: 79185
diff 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: 79502
diff changeset
   966
              _state =
79904
1cfc913987d9 clarified names;
wenzelm
parents: 79898
diff changeset
   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: 79844
diff changeset
   968
                  db, build_id, worker_uuid, _state, old_state)
79904
1cfc913987d9 clarified names;
wenzelm
parents: 79898
diff changeset
   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: 79185
diff 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: 79185
diff 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: 79185
diff 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: 79185
diff 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: 79185
diff 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: 79185
diff changeset
   975
79290
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
   976
    /* build process */
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
   977
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79289
diff 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: 79289
diff changeset
   980
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79293
diff 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: 79895
diff changeset
   983
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   984
    private var _build_tick: Long = 0L
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   985
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   986
    protected override def build_action(): Boolean =
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   987
      Isabelle_Thread.interrupt_handler(_ => progress.stop()) {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff 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: 79895
diff 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: 79895
diff changeset
   990
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   991
        val finished = synchronized { _state.finished_running() }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   992
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   993
        def sleep: Boolean = {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   994
          build_delay.sleep()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff 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: 79895
diff changeset
   996
          expired || ready || progress.stopped
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   997
        }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   998
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
   999
        finished || sleep
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1000
      }
79290
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1001
  }
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1002
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1003
  abstract class Scheduler_Build_Process(
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1004
    build_context: Build.Context,
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1005
    build_progress: Progress,
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1006
    server: SSH.Server,
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79289
diff changeset
  1008
    require(build_context.master)
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff 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: 79502
diff changeset
  1019
79290
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79289
diff changeset
  1021
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1022
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1023
    /* global resources with common close() operation */
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1024
79934
502525a82d9f remove laziness: no need, and errors during initialization loop with close();
Fabian Huch <huch@in.tum.de>
parents: 79931
diff 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: 79931
diff 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: 79289
diff changeset
  1027
      try {
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79289
diff changeset
  1029
        _log_store.init_database(db)
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1030
        db
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1031
      }
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1032
      catch { case exn: Throwable => close(); throw exn }
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1033
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1034
    override def close(): Unit = {
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1035
      Option(_log_database).foreach(_.close())
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1036
      super.close()
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1037
    }
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1038
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff 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: 79761
diff 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: 79761
diff 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: 79761
diff 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: 79761
diff changeset
  1045
a478fc5cd5bd partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
Fabian Huch <huch@in.tum.de>
parents: 79761
diff 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: 79761
diff changeset
  1047
a478fc5cd5bd partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
Fabian Huch <huch@in.tum.de>
parents: 79761
diff 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: 79761
diff 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: 79946
diff 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: 79761
diff changeset
  1051
      }
a478fc5cd5bd partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
Fabian Huch <huch@in.tum.de>
parents: 79761
diff changeset
  1052
a478fc5cd5bd partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
Fabian Huch <huch@in.tum.de>
parents: 79761
diff 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: 79761
diff changeset
  1054
    }
a478fc5cd5bd partially revert f1f08ca40d96: benchmark data needs to be present before timing data is loaded;
Fabian Huch <huch@in.tum.de>
parents: 79761
diff changeset
  1055
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1056
    private var _host_infos = {
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1057
      val build_hosts =
79878
Fabian Huch <huch@in.tum.de>
parents: 79877
diff changeset
  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
12bb31d01510 more robust type, with explicit default;
wenzelm
parents: 79615
diff changeset
  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: 80274
diff 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: 80274
diff 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: 80274
diff changeset
  1068
    private val timing_data: Timing_Data = {
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 80274
diff changeset
  1071
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 79891
diff 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: 79880
diff 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: 79880
diff 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: 79042
diff changeset
  1119
      Build_Log.private_data.update_sessions(
6977fb0153fb clarified modules: Build_Log.private_data provides raw data access without transaction_lock;
wenzelm
parents: 79042
diff 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: 79042
diff 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: 78968
diff 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: 78968
diff changeset
  1128
      state.ancestor_results(session_name) match {
1b05c2b10c9f finalize current sessions before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 78968
diff 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: 78968
diff changeset
  1130
          store.check_output(
1b05c2b10c9f finalize current sessions before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 78968
diff changeset
  1131
            _database_server, session_name,
80125
wenzelm
parents: 80124
diff changeset
  1132
            sources_shasum = state.sessions(session_name).sources_shasum,
wenzelm
parents: 80124
diff changeset
  1133
            input_shasum = ML_Process.make_shasum(ancestor_results.map(_.output_shasum)),
80128
2fe244c4bb01 clarified signature;
wenzelm
parents: 80125
diff changeset
  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: 78968
diff changeset
  1135
            fresh_build = build_context.fresh_build,
80125
wenzelm
parents: 80124
diff changeset
  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: 78968
diff changeset
  1137
        case _ => false
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
  1138
      }
78969
1b05c2b10c9f finalize current sessions before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 78968
diff 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: 79191
diff 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: 79289
diff 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: 79289
diff 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: 79019
diff changeset
  1144
        val current = state.next_ready.filter(task => is_current(state, task.name))
79187
Fabian Huch <huch@in.tum.de>
parents: 79186
diff changeset
  1145
        if (current.nonEmpty) current.map(_.name)
78969
1b05c2b10c9f finalize current sessions before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 78968
diff changeset
  1146
        else {
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1147
          val start = Date.now()
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1148
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1149
          def completed_since(name: String): Time = {
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1150
            val result = state.results(name)
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 80274
diff changeset
  1152
          }
79193
d1d6dbab2901 compare previous build schedule with new one, to prevent regressions;
Fabian Huch <huch@in.tum.de>
parents: 79192
diff changeset
  1153
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff 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: 80274
diff changeset
  1155
          val inactive_hosts =
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1156
            (for {
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1157
              host <- _host_infos.hosts
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1158
              if !active_hosts0.contains(host.name)
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1159
              jobs = _schedule.next(host.name, state)
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1160
              ancestors = build_context.sessions_structure.build_requirements(jobs)
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1161
              if ancestors.forall(ancestor =>
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1162
                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: 80274
diff changeset
  1163
            } yield host).toSet
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1164
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1165
          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: 80274
diff changeset
  1166
          if (host_infos != _host_infos) {
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1167
            _host_infos = host_infos
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1168
            _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: 80274
diff changeset
  1169
          }
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1170
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1171
          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: 79192
diff changeset
  1172
          val schedule =
79293
1f694e4b2b3a clarified signature;
Fabian Huch <huch@in.tum.de>
parents: 79292
diff changeset
  1173
            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: 79192
diff changeset
  1174
            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: 79192
diff changeset
  1175
80471
12901c03b416 remove inactive (e.g., crashed) hosts from scheduling;
Fabian Huch <huch@in.tum.de>
parents: 80274
diff changeset
  1176
          val elapsed = Date.now() - start
78884
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
  1177
78976
8da0eedd562c tuned message;
Fabian Huch <huch@in.tum.de>
parents: 78975
diff changeset
  1178
          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: 79934
diff changeset
  1179
          progress.echo_if(
7a7f1d5dcfe9 only print schedule if relevant;
Fabian Huch <huch@in.tum.de>
parents: 79934
diff changeset
  1180
            _schedule.deviation(schedule).minutes > 1 && schedule.duration >= Time.seconds(1),
7a7f1d5dcfe9 only print schedule if relevant;
Fabian Huch <huch@in.tum.de>
parents: 79934
diff changeset
  1181
            schedule.message + timing_msg)
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1182
79183
32d00ec387f4 use schedule directly instead of extra cache;
Fabian Huch <huch@in.tum.de>
parents: 79182
diff changeset
  1183
          _schedule = schedule
32d00ec387f4 use schedule directly instead of extra cache;
Fabian Huch <huch@in.tum.de>
parents: 79182
diff changeset
  1184
          _schedule.next(hostname, state)
78969
1b05c2b10c9f finalize current sessions before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 78968
diff changeset
  1185
        }
78845
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
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1188
    override def run(): Build.Results = {
79896
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1189
      val vacuous =
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1190
        synchronized_database("Scheduler_Build_Process.init") {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1191
          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: 79895
diff changeset
  1192
          init_unsynchronized()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1193
          _state.pending.isEmpty
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1194
        }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1195
      if (vacuous) {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1196
        progress.echo_warning("Nothing to build")
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1197
        stop_build()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1198
        Build.Results(build_context)
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1199
      }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1200
      else {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1201
        start_worker()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1202
        _build_cluster.start()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1203
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1204
        try {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1205
          while (!finished()) {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1206
            synchronized_database("Scheduler_Build_Process.main") {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1207
              if (progress.stopped) _state.build_running.foreach(_.cancel())
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1208
              main_unsynchronized()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1209
              for {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1210
                host <- build_context.build_hosts
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1211
                if _schedule.exists_next(host.name, _state)
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1212
              } 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: 79895
diff changeset
  1213
            }
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
  1214
            while (!build_action()) {}
79896
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1215
          }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1216
        }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1217
        finally {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1218
          _build_cluster.stop()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1219
          stop_worker()
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1220
          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: 79502
diff changeset
  1221
        }
f1f08ca40d96 make build process state protected to avoid copying in subclasses (e.g. for database connections);
Fabian Huch <huch@in.tum.de>
parents: 79502
diff changeset
  1222
79896
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1223
        val results = synchronized_database("Scheduler_Build_Process.result") {
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1224
          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: 79895
diff changeset
  1225
          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: 79895
diff changeset
  1226
        }
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1227
        write_build_log(results, _state.results)
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1228
        results
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1229
      }
78845
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
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1232
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: 79185
diff changeset
  1233
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: 79185
diff changeset
  1234
  /** 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: 79185
diff changeset
  1235
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: 79185
diff changeset
  1236
  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: 79185
diff changeset
  1237
    import Build_Process.private_data.{Base, Generic}
79896
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1238
    /* 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: 79185
diff changeset
  1239
79844
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1240
    override lazy val tables: SQL.Tables =
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1241
      SQL.Tables(Schedules.table, Nodes.table)
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1242
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1243
    lazy val all_tables: SQL.Tables =
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1244
      SQL.Tables.list(Build_Process.private_data.tables.list ::: tables.list)
ac40138234ce tuned signature: more uniform SQL.Data instances;
wenzelm
parents: 79835
diff changeset
  1245
79896
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1246
    /* notifications */
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1247
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1248
    def channel_ready(hostname: String): SQL.Notification =
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1249
      SQL.Notification(Build_Process.private_data.channel, payload = hostname)
2c9c5ae99a09 proper IPC for scheduled builds, following 7ae25372ab04;
Fabian Huch <huch@in.tum.de>
parents: 79895
diff changeset
  1250
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: 79185
diff changeset
  1251
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: 79185
diff changeset
  1252
    /* 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: 79185
diff changeset
  1253
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: 79185
diff changeset
  1254
    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: 79185
diff changeset
  1255
      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: 79185
diff changeset
  1256
      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: 79185
diff changeset
  1257
      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: 79189
diff changeset
  1258
      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: 79185
diff changeset
  1259
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1260
      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: 79185
diff changeset
  1261
    }
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: 79185
diff changeset
  1262
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1263
    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: 79189
diff changeset
  1264
      db.execute_query_statementO[Long](
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1265
        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: 79189
diff changeset
  1266
          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: 79189
diff changeset
  1267
          _.long(Schedules.serial)).getOrElse(0L)
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1268
79832
2a3c0a68221c misc tuning: prefer Build_Process.Update operations;
wenzelm
parents: 79829
diff changeset
  1269
    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: 79185
diff changeset
  1270
      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: 79185
diff changeset
  1271
        Schedules.table.select(List(Schedules.build_uuid)),
79832
2a3c0a68221c misc tuning: prefer Build_Process.Update operations;
wenzelm
parents: 79829
diff changeset
  1272
        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: 79185
diff changeset
  1273
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: 79185
diff changeset
  1274
    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: 79185
diff changeset
  1275
      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: 79185
diff changeset
  1276
        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: 79185
diff changeset
  1277
          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: 79185
diff changeset
  1278
          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: 79185
diff changeset
  1279
          { 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: 79185
diff changeset
  1280
            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: 79185
diff changeset
  1281
            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: 79185
diff changeset
  1282
            val start = res.date(Schedules.start)
79287
b88b6ed06334 read serial for schedules (amending 2039f360);
Fabian Huch <huch@in.tum.de>
parents: 79236
diff changeset
  1283
            val serial = res.long(Schedules.serial)
b88b6ed06334 read serial for schedules (amending 2039f360);
Fabian Huch <huch@in.tum.de>
parents: 79236
diff changeset
  1284
            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: 79185
diff 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: 79185
diff changeset
  1286
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: 79185
diff changeset
  1287
      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: 79185
diff changeset
  1288
        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: 79185
diff changeset
  1289
        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: 79185
diff 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: 79185
diff changeset
  1291
    }
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: 79185
diff changeset
  1292
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1293
    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: 79185
diff changeset
  1294
      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: 79185
diff changeset
  1295
        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: 79185
diff changeset
  1296
      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: 79185
diff changeset
  1297
        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: 79185
diff changeset
  1298
        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: 79185
diff changeset
  1299
        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: 79189
diff changeset
  1300
        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: 79185
diff changeset
  1301
      })
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: 79185
diff changeset
  1302
      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: 79185
diff 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: 79185
diff 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: 79185
diff changeset
  1305
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: 79185
diff changeset
  1306
    /* 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: 79185
diff changeset
  1307
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: 79185
diff changeset
  1308
    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: 79185
diff changeset
  1309
      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: 79185
diff changeset
  1310
      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: 79185
diff changeset
  1311
      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: 79185
diff changeset
  1312
      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: 79185
diff changeset
  1313
      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: 79185
diff changeset
  1314
      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: 79185
diff changeset
  1315
      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: 79185
diff changeset
  1316
      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: 79185
diff changeset
  1317
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: 79185
diff changeset
  1318
      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: 79185
diff changeset
  1319
        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: 79185
diff changeset
  1320
          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: 79185
diff changeset
  1321
          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: 79185
diff 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: 79185
diff changeset
  1323
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: 79185
diff changeset
  1324
    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: 79185
diff changeset
  1325
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: 79185
diff changeset
  1326
    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: 79185
diff changeset
  1327
      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: 79185
diff changeset
  1328
        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: 79185
diff changeset
  1329
          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: 79185
diff changeset
  1330
        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: 79185
diff changeset
  1331
        { 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: 79185
diff changeset
  1332
          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: 79185
diff changeset
  1333
          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: 79185
diff changeset
  1334
          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: 79185
diff changeset
  1335
          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: 79185
diff changeset
  1336
          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: 79185
diff changeset
  1337
          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: 79185
diff changeset
  1338
          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: 79185
diff changeset
  1339
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: 79185
diff changeset
  1340
          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: 79185
diff changeset
  1341
          ((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: 79185
diff 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: 79185
diff 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: 79185
diff 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: 79185
diff changeset
  1345
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: 79185
diff changeset
  1346
    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: 79185
diff changeset
  1347
      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: 79185
diff changeset
  1348
      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: 79185
diff changeset
  1349
        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: 79185
diff changeset
  1350
          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: 79185
diff changeset
  1351
          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: 79185
diff changeset
  1352
          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: 79185
diff changeset
  1353
          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: 79185
diff changeset
  1354
          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: 79185
diff changeset
  1355
          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: 79185
diff changeset
  1356
          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: 79185
diff changeset
  1357
          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: 79185
diff 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: 79185
diff changeset
  1359
    }
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: 79185
diff changeset
  1360
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1361
    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: 79189
diff changeset
  1362
      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: 79189
diff changeset
  1363
      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: 79189
diff changeset
  1364
      else {
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1365
        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: 79189
diff changeset
  1366
          case Nil => old_schedule
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1367
          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: 79189
diff changeset
  1368
        }
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: 79185
diff changeset
  1369
      }
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1370
    }
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1371
79904
1cfc913987d9 clarified names;
wenzelm
parents: 79898
diff changeset
  1372
    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: 79189
diff changeset
  1373
      val changed =
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1374
        schedule.generator != old_schedule.generator ||
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1375
        schedule.start != old_schedule.start ||
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1376
        schedule.graph != old_schedule.graph
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1377
      
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1378
      val schedule1 =
79835
866d96915388 clarified modules;
wenzelm
parents: 79834
diff changeset
  1379
        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: 79189
diff changeset
  1380
      if (schedule1.serial != schedule.serial) write_schedule(db, schedule1)
79911
cb06884f1040 tuned whitespace;
Fabian Huch <huch@in.tum.de>
parents: 79910
diff changeset
  1381
79190
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1382
      schedule1
2039f3609884 add serial for build schedule to avoid unnecessary db read/writes;
Fabian Huch <huch@in.tum.de>
parents: 79189
diff changeset
  1383
    }
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: 79185
diff changeset
  1384
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: 79185
diff changeset
  1385
    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: 79185
diff changeset
  1386
      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: 79185
diff changeset
  1387
        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: 79185
diff changeset
  1388
        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: 79185
diff 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: 79185
diff changeset
  1390
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: 79185
diff changeset
  1391
    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: 79185
diff changeset
  1392
      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: 79185
diff changeset
  1393
        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: 79185
diff changeset
  1394
          Base.table.select(List(Base.build_uuid), sql = SQL.where(Base.stop.undefined)),
79832
2a3c0a68221c misc tuning: prefer Build_Process.Update operations;
wenzelm
parents: 79829
diff changeset
  1395
          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: 79185
diff changeset
  1396
80274
cff00b3dddf5 clarified names;
wenzelm
parents: 80128
diff changeset
  1397
      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: 79185
diff changeset
  1398
79832
2a3c0a68221c misc tuning: prefer Build_Process.Update operations;
wenzelm
parents: 79829
diff changeset
  1399
      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: 79185
diff 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: 79185
diff 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: 79185
diff changeset
  1402
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: 79185
diff changeset
  1403
79640
7a2b86a48be0 prefer static object, while class is required for "services";
wenzelm
parents: 79639
diff changeset
  1404
  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: 79655
diff changeset
  1405
    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: 79655
diff changeset
  1406
      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: 79655
diff changeset
  1407
      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: 79655
diff changeset
  1408
    }
b88d73810b50 recover "build_database_server" from 1fa1b32b0379: still required, e.g. in build_benchmark;
wenzelm
parents: 79655
diff changeset
  1409
79108
Fabian Huch <huch@in.tum.de>
parents: 79107
diff changeset
  1410
    def scheduler(timing_data: Timing_Data, context: Build.Context): Scheduler = {
Fabian Huch <huch@in.tum.de>
parents: 79107
diff changeset
  1411
      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: 79109
diff changeset
  1412
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1413
      val is_criticals =
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1414
        List(
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1415
          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: 79109
diff changeset
  1416
          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: 79109
diff changeset
  1417
          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: 79109
diff changeset
  1418
          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: 79109
diff changeset
  1419
      val parallel_threads =
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1420
        List(
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1421
          Path_Time_Heuristic.Fixed_Thread(1),
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1422
          Path_Time_Heuristic.Time_Based_Threads({
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1423
            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: 79109
diff changeset
  1424
            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: 79109
diff changeset
  1425
            case _ => 8
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1426
          }))
79180
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1427
      val machine_splits =
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1428
        List(
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1429
          Path_Time_Heuristic.Critical_Nodes,
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1430
          Path_Time_Heuristic.Fixed_Fraction(0.3),
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1431
          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: 79109
diff changeset
  1432
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1433
      val path_time_heuristics =
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1434
        for {
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1435
          is_critical <- is_criticals
ff68cbfa3550 clarified path time heuristic: configurable parameters for larger search space;
Fabian Huch <huch@in.tum.de>
parents: 79109
diff changeset
  1436
          parallel <- parallel_threads
79180
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1437
          machine_split <- machine_splits
229f49204603 clarified build heuristics parameters;
Fabian Huch <huch@in.tum.de>
parents: 79179
diff changeset
  1438
        } yield
79592
7db599be70cc clarified scheduler: proper split into scheduler, generator, and priority rules (following 32d00ec387f4);
Fabian Huch <huch@in.tum.de>
parents: 79534
diff changeset
  1439
          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: 79925
diff changeset
  1440
      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: 79534
diff changeset
  1441
      val heuristics = default_heuristic :: path_time_heuristics
79928
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1442
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1443
      val initial_schedule_file = context.build_options.string("build_schedule_initial")
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1444
      val initial =
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1445
        proper_string(initial_schedule_file).toList.map(initial_schedule_file =>
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1446
          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: 79927
diff changeset
  1447
cdc87eed26c7 allow specifying initial schedule;
Fabian Huch <huch@in.tum.de>
parents: 79927
diff changeset
  1448
      Optimizer(heuristics.map(Generation_Scheme(_, timing_data, context.build_uuid)), initial)
79089
Fabian Huch <huch@in.tum.de>
parents: 79088
diff changeset
  1449
    }
Fabian Huch <huch@in.tum.de>
parents: 79088
diff changeset
  1450
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1451
    override def open_build_process(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1452
      context: Build.Context,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1453
      progress: Progress,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1454
      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: 78888
diff changeset
  1455
    ): Build_Process =
79290
9deadc9d8872 separate build processes for scheduler and scheduled;
Fabian Huch <huch@in.tum.de>
parents: 79289
diff changeset
  1456
      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: 79914
diff changeset
  1457
      else {
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1458
        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: 79914
diff changeset
  1459
        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: 79914
diff changeset
  1460
          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: 79914
diff changeset
  1461
            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: 79914
diff changeset
  1462
              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: 79914
diff changeset
  1463
          }
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1464
        }
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1465
        else {
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1466
          val finished_schedule =
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1467
            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: 79914
diff changeset
  1468
          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: 79914
diff changeset
  1469
            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: 79914
diff changeset
  1470
              (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: 79914
diff changeset
  1471
          }
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1472
        }
78928
6c2c60b852e0 move timing data into scheduler for more efficient heuristics (e.g., with pre-calculated values);
Fabian Huch <huch@in.tum.de>
parents: 78888
diff changeset
  1473
      }
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1474
  }
79640
7a2b86a48be0 prefer static object, while class is required for "services";
wenzelm
parents: 79639
diff changeset
  1475
  object Build_Engine extends Build_Engine
79091
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1476
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1477
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1478
  /* build schedule */
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1479
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1480
  def build_schedule(
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1481
    options: Options,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1482
    build_hosts: List[Build_Cluster.Host] = Nil,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1483
    selection: Sessions.Selection = Sessions.Selection.empty,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1484
    progress: Progress = new Progress,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1485
    afp_root: Option[Path] = None,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1486
    dirs: List[Path] = Nil,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1487
    select_dirs: List[Path] = Nil,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1488
    infos: List[Sessions.Info] = Nil,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1489
    numa_shuffling: Boolean = false,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1490
    augment_options: String => List[Options.Spec] = _ => Nil,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1491
    session_setup: (String, Session) => Unit = (_, _) => (),
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1492
    cache: Term.Cache = Term.Cache.make()
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1493
  ): Schedule = {
79908
c50c15bd304b remove old build before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 79907
diff changeset
  1494
    Build.build_process(options, build_cluster = true, remove_builds = true)
c50c15bd304b remove old build before generating schedule;
Fabian Huch <huch@in.tum.de>
parents: 79907
diff changeset
  1495
79614
58c0636e0ef5 clarified signature;
wenzelm
parents: 79594
diff changeset
  1496
    val store =
79640
7a2b86a48be0 prefer static object, while class is required for "services";
wenzelm
parents: 79639
diff changeset
  1497
      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: 79090
diff changeset
  1498
    val log_store = Build_Log.store(options, cache = cache)
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1499
    val build_options = store.options
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1500
79648
c2afe3629e22 tuned: avoid shadowing of names;
wenzelm
parents: 79644
diff changeset
  1501
    def main(
79091
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1502
      server: SSH.Server,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1503
      database_server: Option[SQL.Database],
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1504
      log_database: PostgreSQL.Database,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1505
      host_database: SQL.Database
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1506
    ): Schedule = {
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1507
      val full_sessions =
80056
9279e96eb34e clarified signature;
wenzelm
parents: 79947
diff changeset
  1508
        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: 79090
diff changeset
  1509
          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: 79090
diff changeset
  1510
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1511
      val build_deps =
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1512
        Sessions.deps(full_sessions.selection(selection), progress = progress,
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1513
          inlined_files = true).check_errors
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1514
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1515
      val build_context =
79640
7a2b86a48be0 prefer static object, while class is required for "services";
wenzelm
parents: 79639
diff changeset
  1516
        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: 79090
diff changeset
  1517
          build_hosts = build_hosts, hostname = Build.hostname(build_options),
79644
389c1bfa7c3e clarified signature: more standard defaults;
wenzelm
parents: 79640
diff changeset
  1518
          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: 79090
diff changeset
  1519
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1520
      val cluster_hosts = build_context.build_hosts
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1521
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1522
      val hosts_current =
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1523
        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: 79090
diff changeset
  1524
      if (!hosts_current) {
79628
e349a274a932 more robust: always close, despite failure;
wenzelm
parents: 79627
diff changeset
  1525
        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: 79090
diff changeset
  1526
      }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1527
79926
dc4a387a6f02 clarified host: pre-load max threads;
Fabian Huch <huch@in.tum.de>
parents: 79925
diff changeset
  1528
      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: 79871
diff changeset
  1529
      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: 79090
diff changeset
  1530
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1531
      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: 79090
diff changeset
  1532
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1533
      val build_state =
79828
5969ead9f900 clarified data representation: more uniform treatment of State.Pending vs. State.Running;
wenzelm
parents: 79819
diff changeset
  1534
        Build_Process.State(sessions = sessions,
79829
a9da5e99e22f tuned signature;
wenzelm
parents: 79828
diff changeset
  1535
          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: 79090
diff changeset
  1536
79640
7a2b86a48be0 prefer static object, while class is required for "services";
wenzelm
parents: 79639
diff changeset
  1537
      val scheduler = Build_Engine.scheduler(timing_data, build_context)
79105
6e92475ff925 clarified schedule message;
Fabian Huch <huch@in.tum.de>
parents: 79104
diff changeset
  1538
      def schedule_msg(res: Exn.Result[Schedule]): String =
6e92475ff925 clarified schedule message;
Fabian Huch <huch@in.tum.de>
parents: 79104
diff changeset
  1539
        res match { case Exn.Res(schedule) => schedule.message case _ => "" }
6e92475ff925 clarified schedule message;
Fabian Huch <huch@in.tum.de>
parents: 79104
diff changeset
  1540
79594
f933e9153624 performance optimization;
Fabian Huch <huch@in.tum.de>
parents: 79593
diff changeset
  1541
      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: 79534
diff changeset
  1542
      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: 79090
diff changeset
  1543
    }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1544
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1545
    using(store.open_server()) { server =>
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1546
      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: 79090
diff changeset
  1547
        using(log_store.open_database(server = server)) { log_database =>
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1548
          using(store.open_build_database(
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1549
            path = isabelle.Host.private_data.database, server = server)) { host_database =>
79648
c2afe3629e22 tuned: avoid shadowing of names;
wenzelm
parents: 79644
diff changeset
  1550
              main(server, database_server, log_database, host_database)
79091
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1551
          }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1552
        }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1553
      }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1554
    }
06f380099b2e added method to generate build schedules directly;
Fabian Huch <huch@in.tum.de>
parents: 79090
diff changeset
  1555
  }
79181
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1556
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1557
  def write_schedule_graphic(schedule: Schedule, output: Path): Unit = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1558
    import java.awt.geom.{GeneralPath, Rectangle2D}
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1559
    import java.awt.{BasicStroke, Color, Graphics2D}
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1560
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1561
    val line_height = isabelle.graphview.Metrics.default.height
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1562
    val char_width = isabelle.graphview.Metrics.default.char_width
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1563
    val padding = isabelle.graphview.Metrics.default.space_width
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1564
    val gap = isabelle.graphview.Metrics.default.gap
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1565
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1566
    val graph = schedule.graph
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1567
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1568
    def text_width(text: String): Double = text.length * char_width
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1569
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1570
    val generator_height = line_height + padding
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1571
    val hostname_height = generator_height + line_height + padding
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1572
    def time_height(time: Time): Double = time.seconds
79819
wenzelm
parents: 79818
diff changeset
  1573
    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: 79180
diff changeset
  1574
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1575
    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: 79180
diff changeset
  1576
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1577
    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: 79180
diff changeset
  1578
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1579
    case class Range(start: Double, stop: Double) {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1580
      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: 79180
diff changeset
  1581
      def width: Double = stop - start
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1582
    }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1583
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1584
    val rel_node_ranges =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1585
      hosts.toList.flatMap { (hostname, nodes) =>
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1586
        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: 79180
diff changeset
  1587
        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: 79180
diff changeset
  1588
          case ((nodes, allocated), node) =>
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1589
            val width = node_width(node) + padding
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1590
            val parallel = nodes.filter(_.end.time > node.start.time)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1591
            val (last, slots) =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1592
              parallel.sortBy(allocated(_).start).foldLeft((0D, List.empty[Range])) {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1593
                case ((start, ranges), node1) =>
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1594
                  val node_range = allocated(node1)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1595
                  (node_range.stop, ranges ::: Range(start, node_range.start).proper)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1596
              }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1597
            val start =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1598
              (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: 79180
diff changeset
  1599
            (node :: parallel, allocated + (node -> Range(start, start + width)))
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1600
        }._2
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1601
      }.toMap
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1602
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1603
    def host_width(hostname: String) =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1604
      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: 79180
diff changeset
  1605
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1606
    def graph_height(graph: Graph[String, Schedule.Node]): Double =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1607
      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: 79180
diff changeset
  1608
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1609
    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: 79180
diff changeset
  1610
    val (last, host_starts) =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1611
      hosts.keys.foldLeft((0D, Map.empty[String, Double])) {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1612
        case ((previous, starts), hostname) =>
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1613
          (previous + gap + host_width(hostname), starts + (hostname -> previous))
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1614
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1615
    val width = (last - gap).ceil.toInt
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1616
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1617
    def node_start(node: Schedule.Node): Double =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1618
      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: 79180
diff changeset
  1619
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1620
    def paint(gfx: Graphics2D): Unit = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1621
      gfx.setColor(Color.LIGHT_GRAY)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1622
      gfx.fillRect(0, 0, width, height)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1623
      gfx.setRenderingHints(isabelle.graphview.Metrics.rendering_hints)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1624
      gfx.setFont(isabelle.graphview.Metrics.default.font)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1625
      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: 79180
diff changeset
  1626
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1627
      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: 79180
diff changeset
  1628
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1629
      def draw_host(x: Double, hostname: String): Double = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1630
        val nodes = hosts(hostname).map(_.job_name).toSet
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1631
        val width = host_width(hostname)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1632
        val height = 2 * padding + graph_height(graph.restrict(nodes.contains))
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1633
        val padding1 = ((width - text_width(hostname)) / 2) max 0
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1634
        val rect = new Rectangle2D.Double(x, hostname_height, width, height)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1635
        gfx.setColor(Color.BLACK)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1636
        gfx.draw(rect)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1637
        gfx.setColor(Color.GRAY)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1638
        gfx.fill(rect)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1639
        draw_string(hostname, x + padding1, generator_height)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1640
        x + gap + width
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1641
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1642
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1643
      def draw_string(str: String, x: Double, y: Double): Unit = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1644
        gfx.setColor(Color.BLACK)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1645
        gfx.drawString(str, x.toInt, (y + line_height).toInt)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1646
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1647
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1648
      def node_rect(node: Schedule.Node): Rectangle2D.Double = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1649
        val x = node_start(node)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1650
        val y = hostname_height + padding + date_height(node.start)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1651
        val width = node_width(node)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1652
        val height = time_height(node.duration)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1653
        new Rectangle2D.Double(x, y, width, height)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1654
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1655
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1656
      def draw_node(node: Schedule.Node): Rectangle2D.Double = {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1657
        val rect = node_rect(node)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1658
        gfx.setColor(Color.BLACK)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1659
        gfx.draw(rect)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1660
        gfx.setColor(Color.WHITE)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1661
        gfx.fill(rect)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1662
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1663
        def add_text(y: Double, text: String): Double =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1664
          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: 79180
diff changeset
  1665
          else {
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1666
            val padding1 = padding min ((rect.height - (y + line_height)) / 2)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1667
            draw_string(text, rect.x + padding, rect.y + y + padding1)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1668
            y + padding1 + line_height
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1669
          }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1670
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1671
        val node_info = node.node_info
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1672
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1673
        val duration_str = "(" + node.duration.message_hms + ")"
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1674
        val node_str =
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1675
          "on " + proper_string(node_info.toString.stripPrefix(node_info.hostname)).getOrElse("all")
79819
wenzelm
parents: 79818
diff changeset
  1676
        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: 79180
diff changeset
  1677
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1678
        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: 79180
diff changeset
  1679
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1680
        rect
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1681
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1682
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1683
      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: 79180
diff changeset
  1684
        val from_rect = node_rect(from)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1685
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1686
        val path = new GeneralPath()
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1687
        path.moveTo(from_rect.getCenterX, from_rect.getMaxY)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1688
        path.lineTo(to.getCenterX, to.getMinY)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1689
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1690
        gfx.setColor(Color.BLUE)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1691
        gfx.draw(path)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1692
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1693
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1694
      hosts.keys.foldLeft(0D)(draw_host)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1695
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1696
      graph.topological_order.foreach { job_name =>
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1697
        val node = graph.get_node(job_name)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1698
        val rect = draw_node(node)
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1699
79235
d9f0eb441d74 improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
Fabian Huch <huch@in.tum.de>
parents: 79194
diff changeset
  1700
        for {
d9f0eb441d74 improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
Fabian Huch <huch@in.tum.de>
parents: 79194
diff changeset
  1701
          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: 79194
diff changeset
  1702
          pred_node = graph.get_node(pred)
d9f0eb441d74 improve graphical clarity by omitting intra-host dependencies (following ee405c40db72);
Fabian Huch <huch@in.tum.de>
parents: 79194
diff changeset
  1703
          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: 79194
diff changeset
  1704
        } draw_arrow(pred_node, rect)
79181
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1705
      }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1706
    }
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1707
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1708
    val name = output.file_name
9d6d559c9fde added graphical representation of build schedules;
Fabian Huch <huch@in.tum.de>
parents: 79180
diff changeset
  1709
    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: 79180
diff changeset
  1710
    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: 79180
diff changeset
  1711
    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: 79180
diff changeset
  1712
  }
79182
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1713
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1714
79629
4d81c0391da2 tuned comments;
wenzelm
parents: 79628
diff changeset
  1715
  /* Isabelle tool wrapper */
79182
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1716
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1717
  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: 79181
diff changeset
  1718
    { args =>
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1719
      var afp_root: Option[Path] = None
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1720
      val base_sessions = new mutable.ListBuffer[String]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1721
      val select_dirs = new mutable.ListBuffer[Path]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1722
      val build_hosts = new mutable.ListBuffer[Build_Cluster.Host]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1723
      var numa_shuffling = false
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1724
      var output_file: Option[Path] = None
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1725
      var requirements = false
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1726
      val exclude_session_groups = new mutable.ListBuffer[String]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1727
      var all_sessions = false
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1728
      val dirs = new mutable.ListBuffer[Path]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1729
      val session_groups = new mutable.ListBuffer[String]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1730
      var options = Options.init(specs = Options.Spec.ISABELLE_BUILD_OPTIONS)
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1731
      var verbose = false
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1732
      val exclude_sessions = new mutable.ListBuffer[String]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1733
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1734
      val getopts = Getopts("""
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1735
Usage: isabelle build_schedule [OPTIONS] [SESSIONS ...]
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1736
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1737
  Options are:
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1738
    -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: 79181
diff changeset
  1739
    -B NAME      include session NAME and all descendants
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1740
    -D DIR       include session directory and select its sessions
79615
a01f4cf202fd tuned usage message;
wenzelm
parents: 79614
diff changeset
  1741
    -H HOSTS     additional cluster host specifications of the form
a01f4cf202fd tuned usage message;
wenzelm
parents: 79614
diff changeset
  1742
                 NAMES:PARAMETERS (separated by commas)
79182
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1743
    -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: 79914
diff changeset
  1744
    -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: 79181
diff changeset
  1745
    -R           refer to requirements of selected sessions
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1746
    -X NAME      exclude sessions from group NAME and all descendants
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1747
    -a           select all sessions
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1748
    -d DIR       include session directory
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1749
    -g NAME      select session group NAME
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1750
    -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: 79181
diff changeset
  1751
    -v           verbose
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1752
    -x NAME      exclude session NAME and all descendants
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1753
79909
Fabian Huch <huch@in.tum.de>
parents: 79908
diff changeset
  1754
  Generate build schedule, but do not run actual build.
79182
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1755
""",
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1756
        "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: 79181
diff changeset
  1757
        "B:" -> (arg => base_sessions += arg),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1758
        "D:" -> (arg => select_dirs += Path.explode(arg)),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1759
        "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: 79181
diff changeset
  1760
        "N" -> (_ => numa_shuffling = true),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1761
        "O:" -> (arg => output_file = Some(Path.explode(arg))),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1762
        "R" -> (_ => requirements = true),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1763
        "X:" -> (arg => exclude_session_groups += arg),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1764
        "a" -> (_ => all_sessions = true),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1765
        "d:" -> (arg => dirs += Path.explode(arg)),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1766
        "g:" -> (arg => session_groups += arg),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1767
        "o:" -> (arg => options = options + arg),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1768
        "v" -> (_ => verbose = true),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1769
        "x:" -> (arg => exclude_sessions += arg))
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1770
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1771
      val sessions = getopts(args)
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1772
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1773
      val progress = new Console_Progress(verbose = verbose)
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1774
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1775
      val schedule =
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1776
        build_schedule(options,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1777
          selection = Sessions.Selection(
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1778
            requirements = requirements,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1779
            all_sessions = all_sessions,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1780
            base_sessions = base_sessions.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1781
            exclude_session_groups = exclude_session_groups.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1782
            exclude_sessions = exclude_sessions.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1783
            session_groups = session_groups.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1784
            sessions = sessions),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1785
          progress = progress,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1786
          afp_root = afp_root,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1787
          dirs = dirs.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1788
          select_dirs = select_dirs.toList,
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1789
          numa_shuffling = isabelle.Host.numa_check(progress, numa_shuffling),
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1790
          build_hosts = build_hosts.toList)
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1791
79915
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1792
      output_file match {
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1793
        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: 79914
diff changeset
  1794
          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: 79914
diff changeset
  1795
            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: 79914
diff changeset
  1796
          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: 79914
diff changeset
  1797
        case _ =>
40d2f9ce29fc allow read/write of schedule in build (read via option, write from tool);
Fabian Huch <huch@in.tum.de>
parents: 79914
diff changeset
  1798
      }
79182
6202d0ff36b4 added build schedule command-line wrapper;
Fabian Huch <huch@in.tum.de>
parents: 79181
diff changeset
  1799
    })
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
  1800
}