src/Pure/Tools/build_schedule.scala
author Fabian Huch <huch@in.tum.de>
Fri, 03 Nov 2023 10:03:05 +0100
changeset 78884 0233d5a5a4ca
parent 78851 db37cae970a6
child 78888 95bbf9a576b3
permissions -rw-r--r--
improved build messages;
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
     1
/*  Title:      Pure/Tools/build_schedule.scala
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
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    10
import scala.annotation.tailrec
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    11
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    12
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    13
object Build_Schedule {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    14
  val engine_name = "build_schedule"
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 Config {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    17
    def from_job(job: Build_Process.Job): Config = Config(job.name, job.node_info)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    18
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    19
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    20
  case class Config(job_name: String, node_info: Node_Info) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    21
    def job_of(start_time: Time): Build_Process.Job =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    22
      Build_Process.Job(job_name, "", "", node_info, Date(start_time), None)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    23
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    24
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    25
  /* organized historic timing information (extracted from build logs) */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    26
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    27
  case class Timing_Entry(job_name: String, hostname: String, threads: Int, elapsed: Time)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    28
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    29
  class Timing_Data private(data: List[Timing_Entry], val host_infos: Host_Infos) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    30
    require(data.nonEmpty)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    31
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    32
    def speedup(time: Time, factor: Double): Time =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    33
      Time.ms((time.ms * factor).toLong)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    34
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    35
    def is_empty = data.isEmpty
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    36
    def size = data.length
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    37
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    38
    private lazy val by_job =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    39
      data.groupBy(_.job_name).view.mapValues(new Timing_Data(_, host_infos)).toMap
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    40
    private lazy val by_threads =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    41
      data.groupBy(_.threads).view.mapValues(new Timing_Data(_, host_infos)).toMap
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    42
    private lazy val by_hostname =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    43
      data.groupBy(_.hostname).view.mapValues(new Timing_Data(_, host_infos)).toMap
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    44
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    45
    def mean_time: Time = Timing_Data.mean_time(data.map(_.elapsed))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    46
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    47
    private def best_entry: Timing_Entry = data.minBy(_.elapsed.ms)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    48
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    49
    def best_threads(job_name: String): Option[Int] = by_job.get(job_name).map(_.best_entry.threads)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    50
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    51
    def best_time(job_name: String): Time =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    52
      by_job.get(job_name).map(_.best_entry.elapsed).getOrElse(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    53
        estimate_config(Config(job_name, Node_Info(best_entry.hostname, None, Nil))))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    54
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    55
    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
    56
      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
    57
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    58
    def approximate_threads(threads: Int): Option[Time] = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    59
      val approximations =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    60
        by_job.values.filter(_.size > 1).map { data =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    61
          val (ref_hostname, x0) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    62
            data.by_hostname.toList.flatMap((hostname, data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    63
              data.by_threads.keys.map(hostname -> _)).minBy((_, n) => Math.abs(n - threads))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    64
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    65
          def unify_hosts(data: Timing_Data): List[Time] =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    66
            data.by_hostname.toList.map((hostname, data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    67
              speedup(data.mean_time, hostname_factor(hostname, ref_hostname)))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    68
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    69
          val entries =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    70
            data.by_threads.toList.map((threads, data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    71
              threads -> Timing_Data.median_time(unify_hosts(data)))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    72
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    73
          val y0 = data.by_hostname(ref_hostname).by_threads(x0).mean_time
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    74
          val (x1, y1_data) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    75
            data.by_hostname(ref_hostname).by_threads.toList.minBy((n, _) => Math.abs(n - threads))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    76
          val y1 = y1_data.mean_time
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    77
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    78
          val a = (y1.ms - y0.ms).toDouble / (x1 - x0)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    79
          val b = y0.ms - a * x0
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    80
          Time.ms((a * threads + b).toLong)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    81
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    82
      if (approximations.isEmpty) None else Some(Timing_Data.mean_time(approximations))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    83
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    84
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    85
    def threads_factor(divided: Int, divisor: Int): Double =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    86
      (approximate_threads(divided), approximate_threads(divisor)) match {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    87
        case (Some(dividend), Some(divisor)) => dividend.ms.toDouble / divisor.ms
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    88
        case _ => divided.toDouble / divisor
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    89
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    90
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    91
    def estimate_config(config: Config): Time =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    92
      by_job.get(config.job_name) match {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    93
        case None => mean_time
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    94
        case Some(data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    95
          val hostname = config.node_info.hostname
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    96
          val threads = host_infos.num_threads(config.node_info)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    97
          data.by_threads.get(threads) match {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    98
            case None => // interpolate threads
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
    99
              data.by_hostname.get(hostname).flatMap(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   100
                _.approximate_threads(threads)).getOrElse {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   101
                  // per machine, try to approximate config for threads
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   102
                  val approximated =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   103
                    data.by_hostname.toList.flatMap((hostname1, data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   104
                      data.approximate_threads(threads).map(time =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   105
                        speedup(time, hostname_factor(hostname1, hostname))))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   106
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   107
                  if (approximated.nonEmpty) Timing_Data.mean_time(approximated)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   108
                  else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   109
                    // no machine where config can be approximated
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   110
                    data.approximate_threads(threads).getOrElse {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   111
                      // only single data point, use global curve to approximate
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   112
                      val global_factor = threads_factor(data.by_threads.keys.head, threads)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   113
                      speedup(data.by_threads.values.head.mean_time, global_factor)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   114
                    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   115
                  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   116
                }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   117
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   118
            case Some(data) => // time for job/thread exists, interpolate machine
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   119
              data.by_hostname.get(hostname).map(_.mean_time).getOrElse {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   120
                Timing_Data.median_time(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   121
                  data.by_hostname.toList.map((hostname1, data) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   122
                    speedup(data.mean_time, hostname_factor(hostname1, hostname))))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   123
              }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   124
          }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   125
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   126
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   127
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   128
  object Timing_Data {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   129
    def median_time(obs: List[Time]): Time = obs.sortBy(_.ms).drop(obs.length / 2).head
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   130
    def mean_time(obs: Iterable[Time]): Time = Time.ms(obs.map(_.ms).sum / obs.size)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   131
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   132
    private val dummy_entries =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   133
      List(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   134
        Timing_Entry("dummy", "dummy", 1, Time.minutes(5)),
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   135
        Timing_Entry("dummy", "dummy", 8, Time.minutes(1)))
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
    def dummy: Timing_Data = new Timing_Data(dummy_entries, Host_Infos.dummy)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   138
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   139
    def make(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   140
      host_infos: Host_Infos,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   141
      build_history: List[(Build_Log.Meta_Info, Build_Log.Build_Info)],
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   142
    ): Timing_Data = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   143
      val hosts = host_infos.hosts
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   144
      val measurements =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   145
        for {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   146
          (meta_info, build_info) <- build_history
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   147
          build_host <- meta_info.get(Build_Log.Prop.build_host).toList
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   148
          (job_name, session_info) <- build_info.sessions.toList
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   149
          hostname = session_info.hostname.getOrElse(build_host)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   150
          host <- hosts.find(_.info.hostname == build_host).toList
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   151
          threads = session_info.threads.getOrElse(host.info.num_cpus)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   152
        } yield (job_name, hostname, threads) -> session_info.timing.elapsed
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   153
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   154
      val entries =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   155
        if (measurements.isEmpty) dummy_entries
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   156
        else
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   157
          measurements.groupMap(_._1)(_._2).toList.map {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   158
            case ((job_name, hostname, threads), timings) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   159
              Timing_Entry(job_name, hostname, threads, median_time(timings))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   160
          }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   161
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   162
      new Timing_Data(entries, host_infos)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   163
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   164
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   165
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   166
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   167
  /* host information */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   168
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   169
  case class Host(info: isabelle.Host.Info, build: Build_Cluster.Host)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   170
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   171
  object Host_Infos {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   172
    def dummy: Host_Infos =
78846
966aa081929f tuned imports;
wenzelm
parents: 78845
diff changeset
   173
      new Host_Infos(
966aa081929f tuned imports;
wenzelm
parents: 78845
diff changeset
   174
        List(Host(isabelle.Host.Info("dummy", Nil, 8, Some(1.0)), Build_Cluster.Host("dummy"))))
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   175
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   176
    def apply(build_hosts: List[Build_Cluster.Host], db: SQL.Database): Host_Infos = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   177
      def get_host(build_host: Build_Cluster.Host): Host = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   178
        val info =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   179
          isabelle.Host.read_info(db, build_host.name).getOrElse(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   180
            error("No benchmark for " + quote(build_host.name)))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   181
        Host(info, build_host)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   182
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   183
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   184
      new Host_Infos(build_hosts.map(get_host))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   185
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   186
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   187
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   188
  class Host_Infos private(val hosts: List[Host]) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   189
    private val by_hostname = hosts.map(host => host.info.hostname -> host).toMap
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   190
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   191
    def host_factor(from: Host, to: Host): Double =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   192
      from.info.benchmark_score.get / to.info.benchmark_score.get
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   193
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   194
    val host_speeds: Ordering[Host] =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   195
      Ordering.fromLessThan((host1, host2) => host_factor(host1, host2) > 1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   196
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   197
    def the_host(hostname: String): Host =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   198
      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
   199
    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
   200
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   201
    def num_threads(node_info: Node_Info): Int =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   202
      if (node_info.rel_cpus.nonEmpty) node_info.rel_cpus.length
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   203
      else the_host(node_info).info.num_cpus
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   204
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   205
    def available(state: Build_Process.State): Resources = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   206
      val allocated =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   207
        state.running.values.map(_.node_info).groupMapReduce(the_host)(List(_))(_ ::: _)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   208
      Resources(this, allocated)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   209
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   210
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   211
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   212
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   213
  /* offline tracking of resource allocations */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   214
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   215
  case class Resources(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   216
    host_infos: Host_Infos,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   217
    allocated_nodes: Map[Host, List[Node_Info]]
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   218
  ) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   219
    val unused_hosts: List[Host] = host_infos.hosts.filter(allocated(_).isEmpty)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   220
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   221
    def allocated(host: Host): List[Node_Info] = allocated_nodes.getOrElse(host, Nil)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   222
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   223
    def allocate(node: Node_Info): Resources = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   224
      val host = host_infos.the_host(node)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   225
      copy(allocated_nodes = allocated_nodes + (host -> (node :: allocated(host))))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   226
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   227
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   228
    def try_allocate_tasks(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   229
      hosts: List[Host],
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   230
      tasks: List[(Build_Process.Task, Int)]
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   231
    ): (List[Config], Resources) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   232
      tasks match {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   233
        case Nil => (Nil, this)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   234
        case (task, threads) :: tasks =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   235
          val (config, resources) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   236
            hosts.find(available(_, threads)) match {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   237
              case Some(host) =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   238
                val node_info = next_node(host, threads)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   239
                (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
   240
              case None => (None, this)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   241
            }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   242
          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
   243
          (configs ++ config, resources1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   244
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   245
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   246
    def next_node(host: Host, threads: Int): Node_Info = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   247
      val numa_node_num_cpus = host.info.num_cpus / (host.info.numa_nodes.length max 1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   248
      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
   249
        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
   250
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   251
      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
   252
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   253
      val available_nodes = host.info.numa_nodes
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   254
      val numa_node =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   255
        if (!host.build.numa) None
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   256
        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
   257
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   258
      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
   259
      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
   260
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   261
      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
   262
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   263
      Node_Info(host.info.hostname, numa_node, rel_cpus)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   264
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   265
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   266
    def available(host: Host, threads: Int): Boolean = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   267
      val used = allocated(host)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   268
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   269
      if (used.length >= host.build.jobs) false
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   270
      else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   271
        if (host.info.numa_nodes.length <= 1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   272
          used.map(host_infos.num_threads).sum + threads <= host.info.num_cpus
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   273
        else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   274
          def node_threads(n: Int): Int =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   275
            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
   276
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   277
          host.info.numa_nodes.exists(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   278
            node_threads(_) + threads <= host.info.num_cpus / host.info.numa_nodes.length)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   279
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   280
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   281
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   282
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   283
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   284
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   285
  /* schedule generation */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   286
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   287
  case class State(build_state: Build_Process.State, current_time: Time) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   288
    def start(config: Config): State =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   289
      copy(build_state =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   290
        build_state.copy(running = build_state.running +
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   291
          (config.job_name -> config.job_of(current_time))))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   292
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   293
    def step(timing_data: Timing_Data): State = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   294
      val remaining =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   295
        build_state.running.values.toList.map { job =>
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   296
          val elapsed = current_time - job.start_date.time
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   297
          val predicted = timing_data.estimate_config(Config.from_job(job))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   298
          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
   299
          job -> remaining
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   300
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   301
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   302
      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
   303
      else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   304
        val (job, elapsed) = remaining.minBy(_._2.ms)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   305
        State(build_state.remove_running(job.name).remove_pending(job.name), current_time + elapsed)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   306
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   307
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   308
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   309
    def finished: Boolean = build_state.pending.isEmpty && build_state.running.isEmpty
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   310
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   311
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   312
  abstract class Scheduler {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   313
    def ready_jobs(state: Build_Process.State): Build_Process.State.Pending =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   314
      state.pending.filter(entry => entry.is_ready && !state.is_running(entry.name))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   315
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   316
    def next(timing: Timing_Data, state: Build_Process.State): List[Config]
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
    def build_duration(timing_data: Timing_Data, build_state: Build_Process.State): Time = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   319
      @tailrec
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   320
      def simulate(state: State): State =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   321
        if (state.finished) state
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   322
        else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   323
          val state1 =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   324
            next(timing_data, state.build_state).foldLeft(state)(_.start(_)).step(timing_data)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   325
          simulate(state1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   326
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   327
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   328
      val start = Time.now()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   329
      simulate(State(build_state, start)).current_time - start
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   330
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   331
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   332
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   333
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   334
  /* heuristics */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   335
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   336
  class Timing_Heuristic(threshold: Time) extends Scheduler {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   337
    def next(timing_data: Timing_Data, state: Build_Process.State): List[Config] = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   338
      val host_infos = timing_data.host_infos
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   339
      val resources = host_infos.available(state)
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
      def best_threads(task: Build_Process.Task): Int =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   342
        timing_data.best_threads(task.name).getOrElse(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   343
          host_infos.hosts.map(_.info.num_cpus).max min 8)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   344
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   345
      val ready = ready_jobs(state)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   346
      val free = resources.unused_hosts
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   347
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   348
      if (ready.length <= free.length)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   349
        resources.try_allocate_tasks(free, ready.map(task => task -> best_threads(task)))._1
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   350
      else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   351
        val pending_tasks = state.pending.map(_.name).toSet
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   352
        val graph = state.sessions.graph.restrict(pending_tasks)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   353
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   354
        val accumulated_time =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   355
          graph.node_depth(timing_data.best_time(_).ms).filter((name, _) => graph.is_maximal(name))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   356
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   357
        val path_time =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   358
          accumulated_time.flatMap((name, ms) => graph.all_preds(List(name)).map(_ -> ms)).toMap
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   359
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   360
        def is_critical(task: String): Boolean = path_time(task) > threshold.ms
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   361
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   362
        val (critical, other) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   363
          ready.sortBy(task => path_time(task.name)).partition(task => is_critical(task.name))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   364
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   365
        val critical_graph = graph.restrict(is_critical)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   366
        def parallel_paths(node: String): Int =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   367
          critical_graph.imm_succs(node).map(suc => parallel_paths(suc) max 1).sum max 1
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   368
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   369
        val (critical_hosts, other_hosts) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   370
          host_infos.hosts.sorted(host_infos.host_speeds).reverse.splitAt(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   371
            critical.map(_.name).map(parallel_paths).sum)
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
        val (configs1, resources1) =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   374
          resources.try_allocate_tasks(critical_hosts,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   375
            critical.map(task => task -> best_threads(task)))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   376
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   377
        val (configs2, _) = resources1.try_allocate_tasks(other_hosts, other.map(_ -> 1))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   378
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   379
        configs1 ::: configs2
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   380
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   381
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   382
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   383
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   384
  class Meta_Heuristic(schedulers: List[Scheduler]) extends Scheduler {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   385
    require(schedulers.nonEmpty)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   386
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   387
    def next(timing_data: Timing_Data, state: Build_Process.State): List[Config] = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   388
      val (best, _) = schedulers.map(h => h -> h.build_duration(timing_data, state)).minBy(_._2.ms)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   389
      best.next(timing_data, state)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   390
    }
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
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   393
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   394
  /* process for scheduled build */
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
  class Scheduled_Build_Process(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   397
    scheduler: Scheduler,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   398
    build_context: Build.Context,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   399
    build_progress: Progress,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   400
    server: SSH.Server,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   401
  ) extends Build_Process(build_context, build_progress, server) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   402
    protected val start_date = Date.now()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   403
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
    /* global resources with common close() operation */
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
    private final lazy val _log_store: Build_Log.Store = Build_Log.store(build_options)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   408
    private final lazy val _log_database: SQL.Database =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   409
      try {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   410
        val db = _log_store.open_database(server = this.server)
78851
db37cae970a6 more robust init_database();
wenzelm
parents: 78849
diff changeset
   411
        _log_store.init_database(db)
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   412
        db
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   413
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   414
      catch { case exn: Throwable => close(); throw exn }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   415
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   416
    override def close(): Unit = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   417
      super.close()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   418
      Option(_log_database).foreach(_.close())
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   419
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   420
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   421
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   422
    /* previous results via build log */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   423
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   424
    override def open_build_cluster(): Build_Cluster = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   425
      val build_cluster = super.open_build_cluster()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   426
      build_cluster.init()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   427
      if (build_context.master && build_context.max_jobs > 0) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   428
        val benchmark_options = build_options.string("build_hostname") = hostname
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   429
        Benchmark.benchmark(benchmark_options, progress)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   430
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   431
      build_cluster.benchmark()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   432
      build_cluster
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   433
    }
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
    private val timing_data: Timing_Data = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   436
      val cluster_hosts: List[Build_Cluster.Host] =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   437
        if (build_context.max_jobs == 0) build_context.build_hosts
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   438
        else {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   439
          val local_build_host =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   440
            Build_Cluster.Host(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   441
              hostname, jobs = build_context.max_jobs, numa = build_context.numa_shuffling)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   442
          local_build_host :: build_context.build_hosts
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   443
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   444
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   445
      val host_infos = Host_Infos(cluster_hosts, _host_database)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   446
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   447
      val build_history =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   448
        for {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   449
          log_name <- _log_database.execute_query_statement(
78849
df162316b6a7 clarified names;
wenzelm
parents: 78846
diff changeset
   450
            Build_Log.private_data.meta_info_table.select(List(Build_Log.private_data.log_name)),
df162316b6a7 clarified names;
wenzelm
parents: 78846
diff changeset
   451
            List.from[String], res => res.string(Build_Log.private_data.log_name))
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   452
          meta_info <- _log_store.read_meta_info(_log_database, log_name)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   453
          build_info = _log_store.read_build_info(_log_database, log_name)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   454
        } yield (meta_info, build_info)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   455
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   456
      Timing_Data.make(host_infos, build_history)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   457
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   458
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   459
    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
   460
      val sessions =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   461
        for {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   462
          (session_name, result) <- state.toList
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   463
          if !result.current
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   464
        } yield {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   465
          val info = build_context.sessions_structure(session_name)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   466
          val entry =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   467
            if (!results.cancelled(session_name)) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   468
              val status =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   469
                if (result.ok) Build_Log.Session_Status.finished
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   470
                else Build_Log.Session_Status.failed
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   471
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   472
              Build_Log.Session_Entry(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   473
                chapter = info.chapter,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   474
                groups = info.groups,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   475
                hostname = Some(result.node_info.hostname),
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   476
                threads = Some(timing_data.host_infos.num_threads(result.node_info)),
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   477
                timing = result.process_result.timing,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   478
                sources = Some(result.output_shasum.digest.toString),
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   479
                status = Some(status))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   480
            }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   481
            else
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   482
              Build_Log.Session_Entry(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   483
                chapter = info.chapter,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   484
                groups = info.groups,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   485
                status = Some(Build_Log.Session_Status.cancelled))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   486
          session_name -> entry
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   487
        }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   488
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   489
      val settings =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   490
        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
   491
          name -> Isabelle_System.getenv(name))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   492
      val props =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   493
        List(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   494
          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
   495
          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
   496
          Build_Log.Prop.build_host.name -> hostname,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   497
          Build_Log.Prop.build_start.name -> Build_Log.print_date(start_date))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   498
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   499
      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
   500
      val build_info = Build_Log.Build_Info(sessions.toMap)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   501
      val log_name = Build_Log.log_filename(engine = engine_name, date = start_date)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   502
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   503
      _log_store.update_sessions(_log_database, log_name.file_name, build_info)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   504
      _log_store.update_meta_info(_log_database, log_name.file_name, meta_info)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   505
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   506
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   507
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   508
    /* build process */
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   509
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   510
    case class Cache(state: Build_Process.State, configs: List[Config], estimate: Date) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   511
      def is_current(state: Build_Process.State): Boolean = this.state == state
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   512
      def is_current_estimate(estimate: Date): Boolean =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   513
        this.estimate.time - estimate.time >= Time.seconds(1)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   514
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   515
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   516
    private var cache = Cache(Build_Process.State(), Nil, Date.now())
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   517
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   518
    override def next_node_info(state: Build_Process.State, session_name: String): Node_Info = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   519
      val configs =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   520
        if (cache.is_current(state)) cache.configs
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   521
        else scheduler.next(timing_data, state)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   522
      configs.find(_.job_name == session_name).get.node_info
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   523
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   524
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   525
    override def next_jobs(state: Build_Process.State): List[String] =
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   526
      if (cache.is_current(state)) cache.configs.map(_.job_name)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   527
      else {
78884
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   528
        val start = Time.now()
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   529
        val next = scheduler.next(timing_data, state)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   530
        val estimate = Date(Time.now() + scheduler.build_duration(timing_data, state))
78884
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   531
        val elapsed = Time.now() - start
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   532
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   533
        val timing_msg = if (elapsed.is_relevant) " (in " + elapsed.message + ")" else ""
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   534
        progress.echo_if(build_context.master && !cache.is_current_estimate(estimate),
0233d5a5a4ca improved build messages;
Fabian Huch <huch@in.tum.de>
parents: 78851
diff changeset
   535
          "Estimated completion: " + estimate + timing_msg)
78845
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   536
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   537
        val configs = next.filter(_.node_info.hostname == hostname)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   538
        cache = Cache(state, configs, estimate)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   539
        configs.map(_.job_name)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   540
      }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   541
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   542
    override def run(): Build.Results = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   543
      val results = super.run()
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   544
      if (build_context.master) write_build_log(results, snapshot().results)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   545
      results
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   546
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   547
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   548
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   549
  class Engine extends Build.Engine(engine_name) {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   550
    override def open_build_process(
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   551
      context: Build.Context,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   552
      progress: Progress,
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   553
      server: SSH.Server
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   554
    ): Build_Process = {
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   555
      val heuristics = List(5, 10, 20).map(minutes => Timing_Heuristic(Time.minutes(minutes)))
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   556
      val scheduler = new Meta_Heuristic(heuristics)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   557
      new Scheduled_Build_Process(scheduler, context, progress, server)
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   558
    }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   559
  }
ff96d94957cb add module for faster scheduled builds;
Fabian Huch <huch@in.tum.de>
parents:
diff changeset
   560
}