Skip to content

Commit 0a6d2de

Browse files
committed
Add fine print explaining experimental parameters
1 parent 5c81fb9 commit 0a6d2de

File tree

13 files changed

+703
-348
lines changed

13 files changed

+703
-348
lines changed

graphics-generator/src/main/java/io/quarkus/infra/performance/graphics/GraphicsCommand.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import io.quarkus.infra.performance.graphics.charts.BarChart;
1313
import io.quarkus.infra.performance.graphics.charts.Chart;
14+
import io.quarkus.infra.performance.graphics.charts.CubeChart;
1415
import io.quarkus.infra.performance.graphics.model.BenchmarkData;
1516
import picocli.CommandLine.Command;
1617
import picocli.CommandLine.Parameters;

graphics-generator/src/main/java/io/quarkus/infra/performance/graphics/ImageGenerator.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@
77
import java.io.OutputStreamWriter;
88
import java.io.Writer;
99
import java.nio.charset.StandardCharsets;
10+
import java.util.Collection;
1011
import java.util.function.BiFunction;
1112

1213
import jakarta.enterprise.context.ApplicationScoped;
1314

15+
import org.apache.batik.anim.dom.SAXSVGDocumentFactory;
1416
import org.apache.batik.anim.dom.SVGDOMImplementation;
1517
import org.apache.batik.svggen.SVGGraphics2D;
18+
import org.apache.batik.util.XMLResourceDescriptor;
1619
import org.w3c.dom.DOMImplementation;
1720
import org.w3c.dom.Document;
1821
import org.w3c.dom.Element;
1922

2023
import io.quarkus.infra.performance.graphics.charts.Chart;
24+
import io.quarkus.infra.performance.graphics.charts.InlinedSVG;
2125
import io.quarkus.infra.performance.graphics.model.BenchmarkData;
2226

2327
@ApplicationScoped
@@ -34,10 +38,11 @@ public void generate(BiFunction<SVGGraphics2D, Theme, Chart> chartConstructor, B
3438
svgGenerator.setSVGCanvasSize(new Dimension(1200, 600));
3539

3640
Chart chart = chartConstructor.apply(svgGenerator, theme);
37-
chart.draw(plotDefinition.title(), data.results().getDatasets(plotDefinition.fun()));
41+
chart.draw(plotDefinition.title(), data.results().getDatasets(plotDefinition.fun()), data.config());
3842

3943
Element root = svgGenerator.getRoot();
4044
initialiseFonts(doc, root);
45+
inlineGraphics(doc, root, chart.getInlinedSVGs());
4146

4247
outFile.getParentFile().mkdirs();
4348
try (Writer out = new OutputStreamWriter(new FileOutputStream(outFile), StandardCharsets.UTF_8)) {
@@ -46,6 +51,15 @@ public void generate(BiFunction<SVGGraphics2D, Theme, Chart> chartConstructor, B
4651
}
4752
}
4853

54+
private void inlineGraphics(Document doc, Element root, Collection<InlinedSVG> inlinedSVGs) {
55+
String parser = XMLResourceDescriptor.getXMLParserClassName();
56+
SAXSVGDocumentFactory factory = new SAXSVGDocumentFactory(parser);
57+
58+
for (InlinedSVG inlinedSVG : inlinedSVGs) {
59+
inlinedSVG.draw(factory, root, doc);
60+
}
61+
}
62+
4963
private static void initialiseFonts(Document doc, Element root) {
5064
Element style = doc.createElementNS(svgNS, "style");
5165
style.setTextContent(Theme.FONT.getCss());

graphics-generator/src/main/java/io/quarkus/infra/performance/graphics/charts/BarChart.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
44

55
import java.awt.Font;
66
import java.awt.geom.Rectangle2D;
7+
import java.util.Collection;
78
import java.util.List;
89

910
import org.apache.batik.svggen.SVGGraphics2D;
1011

1112
import io.quarkus.infra.performance.graphics.Theme;
13+
import io.quarkus.infra.performance.graphics.model.Config;
1214

1315
public class BarChart implements Chart {
1416
private static final int BAR_THICKNESS = 44;
@@ -19,6 +21,7 @@ public class BarChart implements Chart {
1921
private final int canvasHeight;
2022
private final int canvasWidth;
2123
private final Theme theme;
24+
private FinePrint fineprint;
2225

2326
public BarChart(SVGGraphics2D g, Theme theme) {
2427
this.g = g;
@@ -29,12 +32,11 @@ public BarChart(SVGGraphics2D g, Theme theme) {
2932
}
3033

3134
@Override
32-
public void draw(String title, List<Datapoint> data) {
35+
public void draw(String title, List<Datapoint> data, Config metadata) {
3336

3437
g.setPaint(theme.background());
3538
g.fill(new Rectangle2D.Double(0, 0, canvasWidth, canvasWidth));
3639

37-
// --- Draw section titles ---
3840
g.setPaint(theme.text());
3941

4042
double maxValue = data.stream().map(d -> d.value().getValue()).max(Double::compare).orElse(1.0);
@@ -48,7 +50,8 @@ public void draw(String title, List<Datapoint> data) {
4850
new Label(title, 0, titleTextSize).setTargetHeight(titleTextSize).setStyle(Font.BOLD).draw(titleCanvas);
4951

5052
int plotWidth = canvasWidth - 2 * leftMargin;
51-
int plotHeight = canvasHeight - titleCanvas.getHeight();
53+
int finePrintHeight = 80;
54+
int plotHeight = canvasHeight - titleCanvas.getHeight() - finePrintHeight;
5255
Subcanvas chartArea = new Subcanvas(g, plotWidth, plotHeight, leftMargin, titleCanvas.getHeight());
5356

5457
int y = 0;
@@ -57,6 +60,9 @@ public void draw(String title, List<Datapoint> data) {
5760
int fudge = 40;
5861
Subcanvas labelArea = new Subcanvas(chartArea, labelAllowance - fudge, plotHeight, 0, 0);
5962
Subcanvas barArea = new Subcanvas(chartArea, barWidth, plotHeight, labelArea.getWidth(), 0);
63+
int finePrintPadding = 300;
64+
Subcanvas finePrintArea = new Subcanvas(chartArea, barWidth - 2 * finePrintPadding, finePrintHeight, finePrintPadding,
65+
barArea.getHeight() - 50); // TODO Arbitrary fudge padding, remove when scaling work is done
6066

6167
for (Datapoint d : data) {
6268
// If this framework isn't found, it will just be the text colour, which is fine
@@ -79,6 +85,14 @@ public void draw(String title, List<Datapoint> data) {
7985
y += BAR_THICKNESS + barSpacing;
8086

8187
}
88+
89+
this.fineprint = new FinePrint(finePrintArea, theme);
90+
fineprint.draw(metadata);
91+
}
92+
93+
@Override
94+
public Collection<InlinedSVG> getInlinedSVGs() {
95+
return fineprint.getInlinedSVGs();
8296
}
8397

8498
}
Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,18 @@
11
package io.quarkus.infra.performance.graphics.charts;
22

3+
import java.util.Collection;
4+
import java.util.Collections;
35
import java.util.List;
46

7+
import io.quarkus.infra.performance.graphics.model.Config;
8+
59
public interface Chart {
610

7-
void draw(String title, List<Datapoint> datasets);
11+
void draw(String title, List<Datapoint> datasets, Config metadata);
12+
13+
// SVGs after to be done *after* the main drawing, because getting the document root before drawing causes all subsequent draws to be dropped.
14+
// This seems to be a characteristic of the Batik streaming model.
15+
default Collection<InlinedSVG> getInlinedSVGs() {
16+
return Collections.emptyList();
17+
}
818
}

graphics-generator/src/main/java/io/quarkus/infra/performance/graphics/CubeChart.java renamed to graphics-generator/src/main/java/io/quarkus/infra/performance/graphics/charts/CubeChart.java

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
package io.quarkus.infra.performance.graphics;
1+
package io.quarkus.infra.performance.graphics.charts;
22

33
import static java.lang.Math.round;
44

55
import java.awt.Font;
66
import java.awt.geom.Rectangle2D;
7+
import java.util.Collection;
78
import java.util.List;
89

910
import org.apache.batik.svggen.SVGGraphics2D;
1011

11-
import io.quarkus.infra.performance.graphics.charts.Alignment;
12-
import io.quarkus.infra.performance.graphics.charts.Chart;
13-
import io.quarkus.infra.performance.graphics.charts.Datapoint;
14-
import io.quarkus.infra.performance.graphics.charts.Label;
15-
import io.quarkus.infra.performance.graphics.charts.Subcanvas;
12+
import io.quarkus.infra.performance.graphics.Theme;
13+
import io.quarkus.infra.performance.graphics.VAlignment;
14+
import io.quarkus.infra.performance.graphics.model.Config;
1615

1716
public class CubeChart implements Chart {
1817
private static final int BAR_THICKNESS = 44;
@@ -23,6 +22,7 @@ public class CubeChart implements Chart {
2322
private final int canvasHeight;
2423
private final int canvasWidth;
2524
private final Theme theme;
25+
private FinePrint fineprint;
2626

2727
public CubeChart(SVGGraphics2D g, Theme theme) {
2828
this.g = g;
@@ -33,7 +33,7 @@ public CubeChart(SVGGraphics2D g, Theme theme) {
3333
}
3434

3535
@Override
36-
public void draw(String title, List<Datapoint> data) {
36+
public void draw(String title, List<Datapoint> data, Config metadata) {
3737

3838
g.setPaint(theme.background());
3939
g.fill(new Rectangle2D.Double(0, 0, canvasWidth, canvasWidth));
@@ -53,6 +53,11 @@ public void draw(String title, List<Datapoint> data) {
5353
int plotHeight = canvasHeight - titleCanvas.getHeight();
5454

5555
Subcanvas plotArea = new Subcanvas(g, plotWidth, plotHeight, leftMargin, titleCanvas.getHeight());
56+
int finePrintHeight = 80;
57+
int finePrintPadding = 300;
58+
Subcanvas finePrintArea = new Subcanvas(g, plotArea.getWidth() - 2 * finePrintPadding, finePrintHeight,
59+
finePrintPadding,
60+
plotArea.getHeight() - 50); // TODO Arbitrary fudge padding, remove when scaling work is done);
5661

5762
int cubePadding = 1;
5863

@@ -107,6 +112,12 @@ public void draw(String title, List<Datapoint> data) {
107112
x += dataArea.getWidth() + dataPadding;
108113

109114
}
115+
this.fineprint = new FinePrint(finePrintArea, theme);
116+
fineprint.draw(metadata);
110117
}
111118

119+
@Override
120+
public Collection<InlinedSVG> getInlinedSVGs() {
121+
return fineprint.getInlinedSVGs();
122+
}
112123
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package io.quarkus.infra.performance.graphics.charts;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.Collections;
6+
import java.util.Comparator;
7+
import java.util.List;
8+
9+
import io.quarkus.infra.performance.graphics.Theme;
10+
import io.quarkus.infra.performance.graphics.VAlignment;
11+
import io.quarkus.infra.performance.graphics.model.Config;
12+
13+
public class FinePrint {
14+
15+
private static final int padding = 60;
16+
17+
private final Subcanvas g;
18+
private final int canvasHeight;
19+
private final int canvasWidth;
20+
private final Theme theme;
21+
private InlinedSVG svg;
22+
23+
public FinePrint(Subcanvas g, Theme theme) {
24+
this.g = g;
25+
this.theme = theme;
26+
this.canvasHeight = g.getHeight();
27+
this.canvasWidth = g.getWidth();
28+
29+
}
30+
31+
public void draw(Config metadata) {
32+
33+
g.setPaint(theme.background());
34+
35+
g.setPaint(theme.text());
36+
37+
List<String> leftColumn = new ArrayList<>();
38+
List<String> rightColumn = new ArrayList();
39+
40+
if (metadata.quarkus() != null) {
41+
leftColumn.add("Quarkus: "
42+
+ metadata.quarkus().version());
43+
}
44+
if (metadata.springboot() != null) {
45+
leftColumn.add("Spring: "
46+
+ metadata.springboot().version());
47+
}
48+
if (metadata.jvm() != null) {
49+
50+
if (metadata.jvm().graalVM() != null) {
51+
leftColumn.add("JVM: "
52+
+ metadata.jvm().graalVM().version());
53+
}
54+
leftColumn.add("GraalVM: "
55+
+ metadata.jvm().version());
56+
57+
if (metadata.jvm().memory() != null) {
58+
rightColumn.add("Memory: "
59+
+ metadata.jvm().memory());
60+
}
61+
62+
if (metadata.jvm().args() != null && metadata.jvm().args().contains("-XX:ActiveProcessorCount=")) {
63+
// TODO risky calculation, what if the core is a cgroup or something else and not an arg?
64+
rightColumn.add("CPUs: "
65+
+ metadata.jvm().args().replace("-XX:ActiveProcessorCount=", ""));
66+
}
67+
68+
if (metadata.repo() != null) {
69+
rightColumn.add("Source code: "
70+
+ metadata.repo().url().replace("https://github.com/", " ").replaceAll(".git$", ""));
71+
// Use a few spaces to leave room for a logo
72+
}
73+
}
74+
75+
if (!"main".equals(metadata.repo().branch())) {
76+
rightColumn.add("Branch: " + metadata.repo().branch());
77+
78+
}
79+
80+
// Make sure font sizes are the same
81+
// TODO this can go away when we have label groups
82+
while (rightColumn.size() < leftColumn.size()) {
83+
// Put the padding before the last source control line
84+
rightColumn.add(rightColumn.size() - 1, " ");
85+
}
86+
87+
Label leftLabel = new Label(leftColumn.toArray(String[]::new), 0, 0)
88+
.setHorizontalAlignment(Alignment.LEFT)
89+
.setVerticalAlignment(VAlignment.TOP)
90+
.setTargetHeight(g.getHeight());
91+
leftLabel.draw(g);
92+
93+
int leftLabelWidth = leftLabel
94+
.calculateWidth(leftColumn.stream().max(Comparator.comparingInt(String::length)).orElse(""));
95+
int rightLabelX = leftLabelWidth
96+
+ padding;
97+
Label rightLabel = new Label(rightColumn.toArray(String[]::new), rightLabelX, 0)
98+
.setHorizontalAlignment(Alignment.LEFT)
99+
.setVerticalAlignment(VAlignment.TOP)
100+
.setTargetHeight(g.getHeight());
101+
rightLabel.draw(g);
102+
int sw = rightLabel.calculateWidth("Source code:");
103+
104+
if (metadata.repo() != null) {
105+
int logoSize = rightLabel.getAscent();
106+
int logoX = g.getXOffset() + rightLabelX + sw + 2;
107+
int logoY = g.getYOffset() + (rightColumn.size()) * rightLabel.getLineHeight() - rightLabel.getAscent()
108+
+ rightLabel.getDescent() / 2;
109+
this.svg = new InlinedSVG(getPath(theme), logoSize,
110+
logoX,
111+
logoY);
112+
}
113+
}
114+
115+
private static String getPath(Theme theme) {
116+
if (theme == Theme.DARK) {
117+
return "/github-mark-dark.svg";
118+
} else {
119+
return "/github-mark-light.svg";
120+
}
121+
}
122+
123+
public Collection<InlinedSVG> getInlinedSVGs() {
124+
if (svg == null) {
125+
return Collections.emptyList();
126+
}
127+
return List.of(svg);
128+
}
129+
}

0 commit comments

Comments
 (0)