Skip to content

Commit 848e8b6

Browse files
committed
Produce charts from benchmark report
1 parent 2b5fb0b commit 848e8b6

File tree

4 files changed

+102
-2
lines changed

4 files changed

+102
-2
lines changed

benchmarks/time/src/main/scala/strawman/collection/mutable/ArrayBufferBenchmark.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package strawman.collection.mutable
33
import java.util.concurrent.TimeUnit
44

55
import org.openjdk.jmh.annotations._
6-
import strawman.collection.mutable.ArrayBuffer
76
import scala.{Any, AnyRef, Int, Unit}
87

98
@BenchmarkMode(scala.Array(Mode.AverageTime))

build.sbt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,18 @@ val timeBenchmark =
2626
project.in(file("benchmarks/time"))
2727
.dependsOn(collections)
2828
.enablePlugins(JmhPlugin)
29+
.settings(
30+
// runs the benchmarks and produce charts
31+
InputKey[Unit]("charts") := {
32+
val benchmarks = Def.spaceDelimited().parsed
33+
val targetDir = crossTarget.value / "bencharts"
34+
val jmhReport = targetDir / "jmh-result.json"
35+
val jmhArgs = s" -rf json -rff ${jmhReport.absolutePath} $benchmarks"
36+
// HACK We should use `jmhArgs` here
37+
val _ = (run in Jmh).partialInput(" -rf json -rff target/scala-2.12/bencharts/jmh-result.json").evaluated
38+
strawman.collection.Bencharts(jmhReport, targetDir)
39+
}
40+
)
2941

3042
val memoryBenchmark =
3143
project.in(file("benchmarks/memory"))

project/Bencharts.scala

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package strawman.collection
2+
3+
import javax.imageio.ImageIO
4+
5+
import org.jfree.chart.JFreeChart
6+
import org.jfree.chart.axis.{LogAxis, NumberAxis}
7+
import org.jfree.chart.plot.XYPlot
8+
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer
9+
import org.jfree.data.xy.{XYSeries, XYSeriesCollection}
10+
import play.api.libs.json.{JsObject, Json}
11+
import sbt._
12+
13+
object Bencharts {
14+
15+
/**
16+
* Generate charts from the result of a JMH execution.
17+
*
18+
* Benchmarks that have the same name (e.g. `cons`) are grouped
19+
* into a single chart with one series for each.
20+
*
21+
* @param jmhReport JMH results report
22+
* @param targetDir Directory in which the images will be written
23+
*/
24+
def apply(jmhReport: File, targetDir: File): Unit = {
25+
val json = Json.parse(IO.read(jmhReport))
26+
27+
json.as[List[JsObject]]
28+
.groupBy { result =>
29+
val name = (result \ "benchmark").as[String]
30+
val benchmark = name.reverse.takeWhile(_ != '.').reverse
31+
benchmark // Benchmark name (e.g. "cons", "foreach", "map")
32+
}
33+
.foreach { case (benchmark, results) =>
34+
val seriess =
35+
results
36+
// group by concrete collection type
37+
.groupBy(result => (result \ "benchmark").as[String].stripSuffix(benchmark))
38+
.map { case (collectionType, iterations) =>
39+
val xySeries = new XYSeries(collectionType)
40+
// each benchmark has been run with several collection sizes (8, 64, 512, etc.)
41+
// we add a point for each of these iterations
42+
for (iteration <- iterations) {
43+
xySeries.add(
44+
(iteration \ "params" \ "size").as[String].toDouble,
45+
(iteration \ "primaryMetric" \ "score").as[Double]
46+
)
47+
}
48+
xySeries
49+
}
50+
51+
val xAxis = new LogAxis("Size")
52+
xAxis.setBase(2)
53+
xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits())
54+
val yAxis = new LogAxis("Execution time (lower is better)")
55+
56+
val col = new XYSeriesCollection()
57+
for (series <- seriess) {
58+
col.addSeries(series)
59+
}
60+
61+
val plot = new XYPlot(
62+
col,
63+
xAxis, yAxis,
64+
new XYLineAndShapeRenderer(true, true)
65+
)
66+
67+
val chart = new JFreeChart(
68+
benchmark,
69+
JFreeChart.DEFAULT_TITLE_FONT,
70+
plot,
71+
true
72+
)
73+
74+
ImageIO.write(
75+
chart.createBufferedImage(640, 480),
76+
"png",
77+
targetDir / s"$benchmark.png"
78+
)
79+
80+
}
81+
}
82+
83+
}

project/plugins.sbt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,7 @@
1-
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.20")
1+
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.20")
2+
3+
// for bencharts
4+
libraryDependencies ++= Seq(
5+
"org.jfree" % "jfreechart" % "1.0.14",
6+
"com.typesafe.play" %% "play-json" % "2.4.10"
7+
)

0 commit comments

Comments
 (0)