/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ********************************************************************************/ package com.analog.lyric.benchmarking; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Map.Entry; import java.util.Properties; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; public class BenchmarkDatasetXmlSerializer { public void serialize(Writer writer, BenchmarkDataset round) { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); Document doc = builder.newDocument(); Element roundElement = doc.createElement("object"); doc.appendChild(roundElement); addTextChild(roundElement, "date", round.getProperties() .getProperty("create.date")); addTextChild(roundElement, "label", round.getProperties() .getProperty("label")); addTextChild(roundElement, "configuration", round.getProperties() .getProperty("configuration")); addProperties(roundElement, round.getProperties(), "label", "create.date", "configuration"); Element benchmarksElement = addChild(roundElement, "benchmarkruns"); benchmarksElement.setAttribute("type", "list"); for (BenchmarkRun benchmarkRun : round.getBenchmarkRuns()) { Element runElement = addChild(benchmarksElement, "object"); addTextChild(runElement, "label", benchmarkRun.getProperties() .getProperty("label")); addTextChild(runElement, "iterations", benchmarkRun .getProperties().getProperty("iterations")); addTextChild(runElement, "warmupIterations", benchmarkRun .getProperties().getProperty("warmupIterations")); addProperties(runElement, benchmarkRun.getProperties(), "label", "warmupIterations", "iterations"); Element gcSamplesElement = addChild(runElement, "gcSamples"); gcSamplesElement.setAttribute("type", "list"); Element memoryUsageSamplesElement = addChild(runElement, "memorySamples"); memoryUsageSamplesElement.setAttribute("type", "list"); Element timeSamplesElement = addChild(runElement, "timeSamples"); timeSamplesElement.setAttribute("type", "list"); for (BenchmarkRunIteration iteration : benchmarkRun .getIterations()) { Properties iterationProperties = iteration.getProperties(); if (iterationProperties .containsKey("gc.collection.count.post")) { Element s = addChild(gcSamplesElement, "object"); addTextChild(s, "label", "pre"); addTextChild( s, "count", String.valueOf(iterationProperties .getProperty("gc.collection.count.pre"))) .setAttribute("type", "integer"); long nanoseconds = (long) 1e6 * Long.parseLong(iterationProperties .getProperty("gc.collection.time.milli.pre")); addTextChild(s, "nanoseconds", String.valueOf(nanoseconds)); s = addChild(gcSamplesElement, "object"); addTextChild(s, "label", "post"); addTextChild( s, "count", String.valueOf(iterationProperties .getProperty("gc.collection.count.post"))) .setAttribute("type", "integer"); nanoseconds = (long) 1e6 * Long.parseLong(iterationProperties .getProperty("gc.collection.time.milli.post")); addTextChild(s, "nanoseconds", String.valueOf(nanoseconds)); } if (iterationProperties.containsKey("nanoseconds.post")) { Element s = addChild(timeSamplesElement, "object"); addTextChild(s, "label", "pre"); long nanoseconds = Long.parseLong(iterationProperties .getProperty("nanoseconds.pre")); addTextChild(s, "nanoseconds", String.valueOf(nanoseconds)); s = addChild(timeSamplesElement, "object"); addTextChild(s, "label", "post"); nanoseconds = Long.parseLong(iterationProperties .getProperty("nanoseconds.post")); addTextChild(s, "nanoseconds", String.valueOf(nanoseconds)); } for (Entry<Object, Object> entry : iteration .getProperties().entrySet()) { String key = (String) entry.getKey(); if (key.equals("heap.allocation")) { String value = (String) entry.getValue(); Element s = addChild(memoryUsageSamplesElement, "object"); addTextChild(s, "label", "memoryAllocation"); addTextChild(s, "bytes", value); } } } } XmlWriter.Write(writer, doc); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (TransformerException e) { e.printStackTrace(); } } private static void addKVP(Node parent, String key, String value) { Document doc = parent.getOwnerDocument(); Element e = doc.createElement("object"); addTextChild(e, "key", key); addTextChild(e, "value", value); parent.appendChild(e); } private static void addProperties(Node parent, Properties properties, String... except) { ArrayList<String> keys = new ArrayList<String>(); for (Object key : properties.keySet()) { keys.add((String) key); } keys.removeAll(Arrays.asList(except)); Collections.sort(keys); Element propertiesElement = addChild(parent, "properties"); propertiesElement.setAttribute("type", "list"); for (String key : keys) { String value = properties.getProperty(key); addKVP(propertiesElement, key, value); } } private static Element addChild(Node parent, String kind) { Document doc = parent.getOwnerDocument(); Element e = doc.createElement(kind); parent.appendChild(e); return e; } private static Element addTextChild(Node parent, String kind, String text) { Document doc = parent.getOwnerDocument(); Element e = doc.createElement(kind); Node t = doc.createTextNode(text); e.appendChild(t); parent.appendChild(e); return e; } }