diff --git a/build.sbt b/build.sbt index 17791adabb504fb507fcf6869308b866761494e6..99f751a6511689c1d6a5ce368d9ebde284ff16d2 100644 --- a/build.sbt +++ b/build.sbt @@ -29,7 +29,8 @@ libraryDependencies ++= Seq( "org.scala-lang" % "scala-compiler" % "2.11.6", "org.scalatest" %% "scalatest" % "2.2.0" % "test", "com.typesafe.akka" %% "akka-actor" % "2.3.4", - "com.storm-enroute" %% "scalameter" % "0.7-SNAPSHOT" % "test" + "com.storm-enroute" %% "scalameter" % "0.7-SNAPSHOT" % "test", + "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.6.0-rc2" ) lazy val scriptName = "leon" diff --git a/src/main/scala/leon/repair/Repairman.scala b/src/main/scala/leon/repair/Repairman.scala index 43349bffc42ed8c43010db6d249178cb0ecdbbdc..26216a3c2510982046b534d91e5679cf63e33925 100644 --- a/src/main/scala/leon/repair/Repairman.scala +++ b/src/main/scala/leon/repair/Repairman.scala @@ -30,6 +30,8 @@ import scala.concurrent.duration._ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeoutMs: Option[Long], repairTimeoutMs: Option[Long]) { val reporter = ctx.reporter + val storeBenchmarks = true + var program = initProgram implicit val debugSection = DebugSectionRepair @@ -41,6 +43,8 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout to.interruptAfter(repairTimeoutMs) { reporter.info(ASCIIHelpers.title("1. Discovering tests for "+fd.id)) + val timer = new Timer().start + val tb = discoverTests() if (tb.invalids.nonEmpty) { @@ -61,11 +65,38 @@ class Repairman(ctx: LeonContext, initProgram: Program, fd: FunDef, verifTimeout printer(tb2.asString("Minimal Failing Tests")) } + val timeTests = timer.stop + timer.start + val synth = getSynthesizer(tb2) try { reporter.info(ASCIIHelpers.title("3. Synthesizing repair")) - val (search, solutions) = synth.validate(synth.synthesize(), allowPartial = false) + val (search0, sols0) = synth.synthesize() + + val timeSynth = timer.stop + timer.start + + val (search, solutions) = synth.validate((search0, sols0), allowPartial = false) + + val timeVerify = timer.stop + + if (storeBenchmarks) { + val be = (BenchmarkEntry.fromContext(ctx) ++ Map( + "function" -> fd.id.name, + "time_tests" -> timeTests, + "time_synthesis" -> timeSynth, + "time_verification" -> timeVerify, + "success" -> solutions.nonEmpty, + "verified" -> solutions.forall(_._2) + )) + + val bh = new BenchmarksHistory("repairs.dat") + + bh += be + + bh.write + } if (synth.settings.generateDerivationTrees) { val dot = new DotGenerator(search.g) diff --git a/src/main/scala/leon/utils/Benchmarks.scala b/src/main/scala/leon/utils/Benchmarks.scala new file mode 100644 index 0000000000000000000000000000000000000000..39b635ba96dbed6ce0ef0f6b51011e165dd5319e --- /dev/null +++ b/src/main/scala/leon/utils/Benchmarks.scala @@ -0,0 +1,70 @@ +package leon +package utils + +import java.io.{File, PrintWriter} +import scala.io.Source + +import com.fasterxml.jackson.databind.{DeserializationFeature, ObjectMapper} +import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper +import com.fasterxml.jackson.module.scala.DefaultScalaModule + +import java.text._ +import java.util.Date + +class BenchmarksHistory(file: File) { + + def this(name: String) = { + this(new File(name)) + } + + val mapper = new ObjectMapper() with ScalaObjectMapper + mapper.registerModule(DefaultScalaModule) + + private[this] var entries: List[BenchmarkEntry] = { + if (file.exists) { + val str = Source.fromFile(file).mkString + + mapper.readValue[List[Map[String, Any]]](str).map(BenchmarkEntry(_)) + } else { + Nil + } + } + + def write(): Unit = { + val json = mapper.writeValueAsString(entries.map(_.fields)) + val pw = new PrintWriter(file) + try { + pw.write(json) + } finally { + pw.close + } + } + + def +=(be: BenchmarkEntry) { + entries :+= be + } + +} + +case class BenchmarkEntry(fields: Map[String, Any]) { + def +(s: String, v: Any) = { + copy(fields + (s -> v)) + } + + def ++(es: Map[String, Any]) = { + copy(fields ++ es) + } +} + +object BenchmarkEntry { + def fromContext(ctx: LeonContext) = { + val date = new Date() + + BenchmarkEntry(Map( + "files" -> ctx.files.map(_.getAbsolutePath).mkString(" "), + "options" -> ctx.options.mkString(" "), + "date" -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date), + "ts" -> (System.currentTimeMillis() / 1000L) + )) + } +} diff --git a/testcases/repair/report.html b/testcases/repair/report.html new file mode 100644 index 0000000000000000000000000000000000000000..2634d343c2df19a8a558e87d41840e4ecbf11d14 --- /dev/null +++ b/testcases/repair/report.html @@ -0,0 +1,123 @@ +<html> + <head> + <script src="http://code.jquery.com/jquery-1.11.3.min.js"></script> + <script src="http://code.highcharts.com/highcharts.js"></script> +<script> + if (window.File && window.FileReader && window.FileList && window.Blob) { + // Great success! All the File APIs are supported. + } else { + alert('The File APIs are not fully supported in this browser.'); + } + + function initGraph(data) { + $('#container').highcharts({ + title: { + text: 'Leon Benchmarks', + x: -20 //center + }, + + xAxis: { + type: 'datetime', + dateTimeLabelFormats: { // don't display the dummy year + month: '%e. %b', + year: '%b' + }, + title: { + text: 'Date' + } + }, + yAxis: { + title: { + text: 'Time (ms)' + }, + min: 0 + }, + tooltip: { + headerFormat: '<b>{series.name}</b><br>', + pointFormat: '{point.x:%e. %b}: {point.y:.2f} ms' + }, + + legend: { + layout: 'vertical', + align: 'right', + verticalAlign: 'middle', + borderWidth: 0 + }, + + plotOptions: { + spline: { + marker: { + enabled: true + } + } + }, + + series: data + }); + } + + $(function () { + + function processData(data) { + var seriesMap = {}; + + for (var i = 0, r; r = data[i]; i++) { + var parts = r.files.split("/") + var name = parts[parts.length-1]+' '+r.function + + var serie = { + "name": name, + "data": [] + }; + + if (name in seriesMap) { + serie = seriesMap[name] + } + + serie.data.push([1000 * r.ts, r.time_synthesis]) + + seriesMap[name] = serie + } + + console.log(seriesMap) + + var res = []; + + for (k in seriesMap) { + res.push(seriesMap[k]) + } + + initGraph(res) + } + + function handleFileSelect(evt) { + var files = evt.target.files; // FileList object + + graphData = []; + // files is a FileList of File objects. List some properties. + + for (var i = 0, f; f = files[i]; i++) { + var reader = new FileReader(); + + reader.onload = (function(theFile) { + return function(e) { + var json = JSON.parse(e.target.result); + processData(json) + }; + })(f); + + reader.readAsText(f) + } + } + + document.getElementById('fileLoader').addEventListener('change', handleFileSelect, false); + }); +</script> + </head> + <body> + <h1>Leon Benchmarks</h1> + <h2>Load Data</h2> + <input type="file" id="fileLoader" name="data" /> + <div id="container" style="min-width: 310px; height: 400px; margin: 0 auto"></div> + </body> +</html>