Skip to content

Commit

Permalink
basic functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
brianfromoregon committed Aug 25, 2014
1 parent 1c9bdc1 commit 37c99fd
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 158 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
Jenkins plugin for [jmh](http://openjdk.java.net/projects/code-tools/jmh)
Jenkins plugin for [jmh](http://openjdk.java.net/projects/code-tools/jmh)

Currently it collects result files as a post-build action, then publishes an index file of all results
across all previous builds. This might be consumed by d3.js to produce visualizations.

![screenshot](http://i.imgur.com/WzwV0qj.png)
18 changes: 7 additions & 11 deletions src/main/java/com/brianfromoregon/jmh/BuildAction.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import hudson.model.AbstractBuild;
import hudson.model.Action;

import java.util.Map;
import java.util.logging.Logger;

import static com.google.common.collect.Lists.transform;
Expand All @@ -27,15 +28,10 @@ public BuildAction(ImmutableList<CollectedFile> results, AbstractBuild<?, ?> bui
}

/**
* /jmh/file/name
* /jmh/files
*/
public String getFile(String name) {
CollectedFile file = resultsByName.get(name);
if (file == null) {
return null;
}

return file.content;
public Map<String, CollectedFile> getFiles() {
return resultsByName;
}

/**
Expand All @@ -54,7 +50,7 @@ public FileIndex getAllResults() {
list.addAll(transform(buildAction.results, new Function<CollectedFile, PublishedFile>() {
@Override
public PublishedFile apply(CollectedFile collectedFile) {
String url = format("%sjmh/file/%s", buildUrl, collectedFile.name());
String url = format("%sjmh/files/%s", buildUrl, collectedFile.name());
return new PublishedFile(collectedFile, url);
}
}));
Expand All @@ -67,13 +63,13 @@ public PublishedFile apply(CollectedFile collectedFile) {
*/
public String getSummary() {
return format("Collected %d result file%s",
results,
results.size(),
results.size() == 1 ? "" : "s");
}

@Override
public String getIconFileName() {
return "/plugin/caliper-ci/caliper.png";
return "/plugin/jmh-plugin/shipilev.jpg";
}

@Override
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/brianfromoregon/jmh/CollectedFile.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
package com.brianfromoregon.jmh;

import au.com.bytecode.opencsv.CSVWriter;
import com.google.common.base.Function;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;

import java.io.IOException;

import static com.google.common.collect.Lists.transform;

/**
*
*/
Expand All @@ -20,4 +29,9 @@ public CollectedFile(String path, String content) {
String name() {
return path.replace('/', '_');
}

public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException {
rsp.setContentType("text/plain");
rsp.getWriter().append(content);
}
}
13 changes: 7 additions & 6 deletions src/main/java/com/brianfromoregon/jmh/FileIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import au.com.bytecode.opencsv.CSVWriter;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import org.jfree.chart.ChartRenderingInfo;
import org.jfree.chart.ChartUtilities;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
Expand All @@ -15,19 +17,17 @@
/**
*
*/
public class FileIndex implements HttpResponse {
public class FileIndex {
// In order, older build results first
final ImmutableList<PublishedFile> results;

public FileIndex(ImmutableList<PublishedFile> results) {
this.results = results;
}

@Override
public void generateResponse(StaplerRequest req, StaplerResponse res, Object o) throws IOException, ServletException {
// TODO support other result types
// String type = req.getParameter("type");
CSVWriter writer = new CSVWriter(res.getWriter());
public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException {
rsp.setContentType("text/csv");
CSVWriter writer = new CSVWriter(rsp.getWriter());
writer.writeNext(new String[] {"url", "path"});
writer.writeAll(transform(results, new Function<PublishedFile, String[]>() {
@Override
Expand All @@ -39,4 +39,5 @@ public String[] apply(PublishedFile result) {
}
}));
}

}
8 changes: 6 additions & 2 deletions src/main/java/com/brianfromoregon/jmh/ResultsRecorder.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
import java.io.IOException;
import java.io.InputStreamReader;

import static org.apache.commons.lang.StringUtils.strip;

/**
* This is my "Post Build Action" which finds result files, stores them, and adds an action to the build.
* <p/>
Expand Down Expand Up @@ -63,15 +65,17 @@ public boolean isApplicable(Class<? extends AbstractProject> aClass) {
}

public String getDisplayName() {
return "Publish JMH microbenchmark results";
return "Publish JMH benchmark results";
}
}

private ImmutableList<CollectedFile> readUtf8Results(AbstractBuild<?, ?> build) throws IOException, InterruptedException {
String workspace = build.getWorkspace().getRemote();
Builder<CollectedFile> list = ImmutableList.builder();
for (FilePath f : build.getWorkspace().list(results)) {
String content = CharStreams.toString(new InputStreamReader(f.read(), Charsets.UTF_8));
list.add(new CollectedFile(f.getRemote(), content));
String name = strip(f.getRemote().substring(workspace.length()).replace('\\', '/'), "/");
list.add(new CollectedFile(name, content));
}
return list.build();
}
Expand Down
138 changes: 2 additions & 136 deletions src/main/resources/com/brianfromoregon/jmh/BuildAction/index.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -5,143 +5,9 @@
<st:include it="${it.build}" page="sidepanel.jelly"/>
<l:main-panel>
<h1>
<img src="/plugin/caliper-ci/caliper.png" alt="" height="48" width="48"/>
Caliper Results
JMH Results
</h1>
<table class="sortable pane bigtable">
<tr>
<th initialSortDir="down">Name</th>
<th>Time</th>
<th>Bytes</th>
<th>Objects</th>
<th>Parameters</th>
</tr>
<j:forEach var="r" items="${it.scenarioResultChanges}">
<tr>
<td height="16px" class="pane">${r.benchmarkName}</td>
<td height="16px" class="pane">${r.timeString}</td>
<j:choose>
<j:when test="${r.bytesType.toString().equals('WORSE')}">
<td height="16px" class="pane"><img src="${imagesURL}/16x16/red.gif"/>${r.bytesString}
</td>
</j:when>
<j:when test="${r.bytesType.toString().equals('BETTER')}">
<td height="16px" class="pane"><img src="${imagesURL}/16x16/blue.gif"/>${r.bytesString}
</td>
</j:when>
<j:otherwise>
<td height="16px" class="pane">${r.bytesString}</td>
</j:otherwise>
</j:choose>
<j:choose>
<j:when test="${r.instancesType.toString().equals('WORSE')}">
<td height="16px" class="pane">
<img src="${imagesURL}/16x16/red.gif"/>
${r.instancesString}
</td>
</j:when>
<j:when test="${r.instancesType.toString().equals('BETTER')}">
<td height="16px" class="pane">
<img src="${imagesURL}/16x16/blue.gif"/>
${r.instancesString}
</td>
</j:when>
<j:otherwise>
<td height="16px" class="pane">${r.instancesString}</td>
</j:otherwise>
</j:choose>
<td height="16px" class="pane">${r.scenario}</td>
</tr>
</j:forEach>
</table>
<h1>
<img src="/plugin/caliper-ci/caliper.png" alt="" height="48" width="48"/>
Trending
</h1>
<table class="sortable pane bigtable">
<tr>
<th initialSortDir="down">Benchmark</th>
<th>Statistics</th>
<th>Timing Trend</th>
</tr>
<j:forEach var="e" items="${it.scenarioTrends}">
<j:set var="stats" value="${e.statistics}"/>
<tr>
<td>
<table class="pane">
<tr>
<td>class</td>
<td>${e.benchmarkName}</td>
</tr>
<j:forEach var="p" items="${e.parameters}">
<tr>
<td>${p.key}</td>
<td>${p.value}</td>
</tr>
</j:forEach>
</table>
</td>
<td>
<table class="pane">
<tr>
<td>N</td>
<td>${stats.n}</td>
</tr>
<tr>
<td>Min</td>
<td>${stats.min}</td>
</tr>
<tr>
<td>Max</td>
<td>${stats.max}</td>
</tr>
<tr>
<td>Mean</td>
<td>${stats.mean}</td>
</tr>
<tr>
<td>Stdev</td>
<td>${stats.standardDeviation}</td>
</tr>
</table>
</td>
<td>
<img src="timingTrendGraph/png?id=${e.id}" lazymap="timingTrendGraph/map?id=${e.id}"
alt="[Timing trend graph]"/>
</td>
</tr>
</j:forEach>
</table>
<h1>
<img src="/plugin/caliper-ci/caliper.png" alt="" height="48" width="48"/>
Environment
</h1>
<table class="sortable pane bigtable">
<tr>
<th initialSortDir="down">Property</th>
<th>Value</th>
</tr>
<j:forEach var="e" items="${it.results.environment.properties}">
<tr>
<td>${e.key}</td>
<td>${e.value}</td>
</tr>
</j:forEach>
</table>
<p style="padding-top: 2em;">
<ul>
<li>Why don't timing results fail the build? That's coming, follow progress
<a href="http://code.google.com/p/caliper-ci/issues/detail?id=5">in this issue</a>.
</li>
<st:nbsp/>
<li>Would you rather see these results looking
<a href="http://microbenchmarks.appspot.com/run/jessewilson@google.com/examples.ArraySortBenchmark">
like this</a>?
Yeah,
<a href="http://code.google.com/p/caliper-ci/issues/detail?id=1">me too!</a>
</li>
</ul>
</p>
<a href="allResults">Index file of results</a>
</l:main-panel>
</l:layout>
</j:jelly>
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout"
xmlns:t="/lib/hudson" xmlns:f="/lib/form">

<t:summary icon="${it.iconFileName}" href="caliper">${it.summary}</t:summary>
<t:summary icon="${it.iconFileName}" href="jmh">${it.summary}</t:summary>

</j:jelly>
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
xmlns:t="/lib/hudson" xmlns:f="/lib/form">

<f:entry title="Result files" field="results" description="${%description}">
<f:textbox default="*.jmh.json"/>
<f:textbox default="**/*.jmh.json"/>
</f:entry>

</j:jelly>
Binary file removed src/main/webapp/caliper.png
Binary file not shown.

0 comments on commit 37c99fd

Please sign in to comment.