| author | blanchet | 
| Mon, 26 May 2014 16:32:51 +0200 | |
| changeset 57090 | 0224caba67ca | 
| parent 53189 | ee8b8dafef0e | 
| child 57612 | 990ffb84489b | 
| permissions | -rw-r--r-- | 
| 51240 | 1 | /* Title: Pure/Tools/ml_statistics.scala | 
| 50685 | 2 | Author: Makarius | 
| 3 | ||
| 4 | ML runtime statistics. | |
| 5 | */ | |
| 6 | ||
| 7 | package isabelle | |
| 8 | ||
| 9 | ||
| 51432 | 10 | import scala.collection.mutable | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 11 | import scala.collection.immutable.{SortedSet, SortedMap}
 | 
| 50691 | 12 | import scala.swing.{Frame, Component}
 | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 13 | |
| 50689 | 14 | import org.jfree.data.xy.{XYSeries, XYSeriesCollection}
 | 
| 15 | import org.jfree.chart.{JFreeChart, ChartPanel, ChartFactory}
 | |
| 16 | import org.jfree.chart.plot.PlotOrientation | |
| 17 | ||
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 18 | |
| 50685 | 19 | object ML_Statistics | 
| 20 | {
 | |
| 50690 | 21 | /* content interpretation */ | 
| 22 | ||
| 23 | final case class Entry(time: Double, data: Map[String, Double]) | |
| 24 | ||
| 50982 | 25 | def apply(name: String, stats: List[Properties.T]): ML_Statistics = | 
| 26 | new ML_Statistics(name, stats) | |
| 50690 | 27 | |
| 50982 | 28 | def apply(info: Build.Log_Info): ML_Statistics = | 
| 29 | apply(info.name, info.stats) | |
| 30 | ||
| 31 |   val empty = apply("", Nil)
 | |
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 32 | |
| 50690 | 33 | |
| 34 | /* standard fields */ | |
| 35 | ||
| 36 |   val GC_fields = ("GCs", List("partial_GCs", "full_GCs"))
 | |
| 37 | ||
| 38 | val heap_fields = | |
| 39 |     ("Heap", List("size_heap", "size_allocation", "size_allocation_free",
 | |
| 40 | "size_heap_free_last_full_GC", "size_heap_free_last_GC")) | |
| 41 | ||
| 42 | val threads_fields = | |
| 43 |     ("Threads", List("threads_total", "threads_in_ML", "threads_wait_condvar",
 | |
| 44 | "threads_wait_IO", "threads_wait_mutex", "threads_wait_signal")) | |
| 45 | ||
| 51432 | 46 |   val time_fields = ("Time", List("time_CPU", "time_GC"))
 | 
| 47 | ||
| 48 |   val speed_fields = ("Speed", List("speed_CPU", "speed_GC"))
 | |
| 50690 | 49 | |
| 50 | val tasks_fields = | |
| 53189 
ee8b8dafef0e
discontinued parallel_subproofs_saturation and related internal counters (superseded by parallel_subproofs_threshold and timing information);
 wenzelm parents: 
52888diff
changeset | 51 |     ("Future tasks", List("tasks_ready", "tasks_pending", "tasks_running", "tasks_passive"))
 | 
| 50690 | 52 | |
| 53 | val workers_fields = | |
| 54 |     ("Worker threads", List("workers_total", "workers_active", "workers_waiting"))
 | |
| 55 | ||
| 56 | val standard_fields = | |
| 51432 | 57 | List(GC_fields, heap_fields, threads_fields, time_fields, speed_fields, | 
| 58 | tasks_fields, workers_fields) | |
| 50685 | 59 | } | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 60 | |
| 50982 | 61 | final class ML_Statistics private(val name: String, val stats: List[Properties.T]) | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 62 | {
 | 
| 50690 | 63 |   val Now = new Properties.Double("now")
 | 
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 64 | def now(props: Properties.T): Double = Now.unapply(props).get | 
| 50690 | 65 | |
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 66 | require(stats.forall(props => Now.unapply(props).isDefined)) | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 67 | |
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 68 | val time_start = if (stats.isEmpty) 0.0 else now(stats.head) | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 69 | val duration = if (stats.isEmpty) 0.0 else now(stats.last) - time_start | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 70 | |
| 50689 | 71 | val fields: Set[String] = | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 72 | SortedSet.empty[String] ++ | 
| 50690 | 73 | (for (props <- stats.iterator; (x, _) <- props.iterator if x != Now.name) | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 74 | yield x) | 
| 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 75 | |
| 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 76 | val content: List[ML_Statistics.Entry] = | 
| 51432 | 77 |   {
 | 
| 78 | var last_edge = Map.empty[String, (Double, Double, Double)] | |
| 79 | val result = new mutable.ListBuffer[ML_Statistics.Entry] | |
| 80 |     for (props <- stats) {
 | |
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 81 | val time = now(props) - time_start | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 82 | require(time >= 0.0) | 
| 51432 | 83 | |
| 84 | // rising edges -- relative speed | |
| 85 | val speeds = | |
| 86 |         for ((key, value) <- props; a <- Library.try_unprefix("time", key)) yield {
 | |
| 52888 | 87 | val (x0, y0, s0) = last_edge.getOrElse(a, (0.0, 0.0, 0.0)) | 
| 51432 | 88 | |
| 89 | val x1 = time | |
| 90 | val y1 = java.lang.Double.parseDouble(value) | |
| 91 | val s1 = if (x1 == x0) 0.0 else (y1 - y0) / (x1 - x0) | |
| 92 | ||
| 93 |           val b = ("speed" + a).intern
 | |
| 94 |           if (y1 > y0) { last_edge += (a -> (x1, y1, s1)); (b, s1) } else (b, s0)
 | |
| 95 | } | |
| 96 | ||
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 97 | val data = | 
| 51432 | 98 | SortedMap.empty[String, Double] ++ speeds ++ | 
| 50690 | 99 | (for ((x, y) <- props.iterator if x != Now.name) | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 100 | yield (x, java.lang.Double.parseDouble(y))) | 
| 51432 | 101 | result += ML_Statistics.Entry(time, data) | 
| 102 | } | |
| 103 | result.toList | |
| 104 | } | |
| 50689 | 105 | |
| 106 | ||
| 107 | /* charts */ | |
| 108 | ||
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 109 | def update_data(data: XYSeriesCollection, selected_fields: Iterable[String]) | 
| 50689 | 110 |   {
 | 
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 111 | data.removeAllSeries | 
| 50689 | 112 |     for {
 | 
| 50690 | 113 | field <- selected_fields.iterator | 
| 50689 | 114 | series = new XYSeries(field) | 
| 115 |     } {
 | |
| 116 | content.foreach(entry => series.add(entry.time, entry.data(field))) | |
| 117 | data.addSeries(series) | |
| 118 | } | |
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 119 | } | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 120 | |
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 121 | def chart(title: String, selected_fields: Iterable[String]): JFreeChart = | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 122 |   {
 | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 123 | val data = new XYSeriesCollection | 
| 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 124 | update_data(data, selected_fields) | 
| 50689 | 125 | |
| 126 | ChartFactory.createXYLineChart(title, "time", "value", data, | |
| 127 | PlotOrientation.VERTICAL, true, true, true) | |
| 128 | } | |
| 129 | ||
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 130 | def chart(arg: (String, Iterable[String])): JFreeChart = chart(arg._1, arg._2) | 
| 50691 | 131 | |
| 50981 | 132 | def show_standard_frames(): Unit = | 
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 133 | ML_Statistics.standard_fields.map(chart(_)).foreach(c => | 
| 50691 | 134 |       Swing_Thread.later {
 | 
| 50854 | 135 |         new Frame {
 | 
| 51615 
072a7249e1ac
separate module "GUI", to keep this out of the way of generic Isabelle_System operations, notably for non-Isabelle/jEdit applications;
 wenzelm parents: 
51432diff
changeset | 136 | iconImage = GUI.isabelle_image() | 
| 50982 | 137 | title = name | 
| 50854 | 138 | contents = Component.wrap(new ChartPanel(c)) | 
| 139 | visible = true | |
| 140 | } | |
| 50697 
82e9178e6a98
improved Monitor_Dockable, based on ML_Statistics operations;
 wenzelm parents: 
50691diff
changeset | 141 | }) | 
| 50688 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 142 | } | 
| 
f02864682307
some support for ML statistics content interpretation;
 wenzelm parents: 
50685diff
changeset | 143 |