blob: 8288d07777b44ac8a0dc5e0b77e3325083d11a13 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2019 Mia-Software and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Gregoire DUPE (Mia-Software)
* Nicolas Bros (Mia-Software) - Bug 335003 - [Discoverer] : Existing Discoverers Refactoring based on new framework
* Nicolas Bros (Mia-Software) - Bug 346207 - Memory behaviour benchmark report charts are empty
*******************************************************************************/
package org.eclipse.modisco.java.discoverer.benchmark;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.eclipse.birt.chart.device.IDeviceRenderer;
import org.eclipse.birt.chart.factory.GeneratedChartState;
import org.eclipse.birt.chart.factory.Generator;
import org.eclipse.birt.chart.model.ChartWithAxes;
import org.eclipse.birt.chart.model.attribute.Bounds;
import org.eclipse.birt.chart.model.attribute.ChartDimension;
import org.eclipse.birt.chart.model.attribute.ColorDefinition;
import org.eclipse.birt.chart.model.attribute.LegendItemType;
import org.eclipse.birt.chart.model.attribute.LineAttributes;
import org.eclipse.birt.chart.model.attribute.LineStyle;
import org.eclipse.birt.chart.model.attribute.impl.BoundsImpl;
import org.eclipse.birt.chart.model.attribute.impl.ColorDefinitionImpl;
import org.eclipse.birt.chart.model.attribute.impl.LineAttributesImpl;
import org.eclipse.birt.chart.model.attribute.impl.TextImpl;
import org.eclipse.birt.chart.model.component.Axis;
import org.eclipse.birt.chart.model.component.ComponentFactory;
import org.eclipse.birt.chart.model.component.Label;
import org.eclipse.birt.chart.model.component.Scale;
import org.eclipse.birt.chart.model.component.Series;
import org.eclipse.birt.chart.model.component.impl.LabelImpl;
import org.eclipse.birt.chart.model.component.impl.SeriesImpl;
import org.eclipse.birt.chart.model.data.NumberDataElement;
import org.eclipse.birt.chart.model.data.NumberDataSet;
import org.eclipse.birt.chart.model.data.SeriesDefinition;
import org.eclipse.birt.chart.model.data.impl.NumberDataSetImpl;
import org.eclipse.birt.chart.model.data.impl.SeriesDefinitionImpl;
import org.eclipse.birt.chart.model.impl.ChartWithAxesImpl;
import org.eclipse.birt.chart.model.type.LineSeries;
import org.eclipse.birt.chart.model.type.impl.LineSeriesImpl;
import org.eclipse.birt.chart.util.PluginSettings;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.modisco.infra.discovery.benchmark.Benchmark;
import org.eclipse.modisco.infra.discovery.benchmark.BenchmarkFactory;
import org.eclipse.modisco.infra.discovery.benchmark.Discovery;
import org.eclipse.modisco.infra.discovery.benchmark.MultiProjectBenchmark;
import org.eclipse.modisco.java.discoverer.benchmark.emfstat.DiscoverJavaModelFromJavaProjectEMFStat;
import org.eclipse.modisco.java.discoverer.benchmark.emfstat.Statistics;
import org.eclipse.modisco.java.discoverer.benchmark.javaBenchmark.CDODiscovery;
import org.eclipse.modisco.java.discoverer.benchmark.javaBenchmark.JavaBenchmarkFactory;
import org.eclipse.modisco.java.discoverer.benchmark.javaBenchmark.JavaDiscoveredProject;
import org.eclipse.modisco.java.discoverer.benchmark.template.html.HtmlReport;
import org.eclipse.modisco.java.discoverer.cdo.JavaDiscovererCDO;
import org.eclipse.swt.graphics.Point;
/**
* @author Gregoire DUPE (Mia-Software)
*
*/
public class Report {
private static final int MINUTE_MS_RANGE = 60000;
private static final int CHART_SIZE = 1000;
private static final int RESCALE_COEF = 10;
private static final double BOUNDS_SCALE_CONST = 72d;
public static final String HTMLREPORT_FILE_NAME = "report.html"; //$NON-NLS-1$
private final IProject statProject;
private final Map<Integer, ArrayList<Float>> map = new HashMap<Integer, ArrayList<Float>>();
private final Map<String, Integer> titleMap = new HashMap<String, Integer>();
private int index = 0;
public Report(final IProject statProject) {
this.statProject = statProject;
}
public MultiProjectBenchmark generate() throws CoreException, IOException {
MultiProjectBenchmark benchmark = buildReportModelAndDiagrams();
generateHTML(benchmark, this.statProject.getLocation().toFile());
return benchmark;
}
private MultiProjectBenchmark buildReportModelAndDiagrams() throws CoreException, IOException {
ResourceSet resourceSet = new ResourceSetImpl();
URI uri = URI.createURI("platform:/resource/" //$NON-NLS-1$
+ this.statProject.getName() + "/report.xmi"); //$NON-NLS-1$
Resource modelResource = resourceSet.createResource(uri);
MultiProjectBenchmark benchmark = BenchmarkFactory.eINSTANCE.createMultiProjectBenchmark();
modelResource.getContents().add(benchmark);
List<IStatus> errors = new ArrayList<IStatus>();
this.statProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
for (IResource resource : this.statProject.members()) {
try {
if (resource instanceof IFile) {
IFile file = (IFile) resource;
if (file.getLocation().getFileExtension().equals(Statistics.TSV_FILE_EXT)) {
String lastLine1 = ""; //$NON-NLS-1$
String lastLine2 = ""; //$NON-NLS-1$
BufferedReader bufferReader = new BufferedReader(new FileReader(file
.getLocation().toFile()));
String line = bufferReader.readLine();
titleLine(line);
line = bufferReader.readLine();
int maxUsedMemory = 0;
while (line != null) {
addToSeries(line);
lastLine2 = lastLine1;
lastLine1 = line;
int usedMemory = new Integer(getValue(line, Statistics.USED_MEMORY));
maxUsedMemory = Math.max(maxUsedMemory, usedMemory);
line = bufferReader.readLine();
}
IResource txtResource = resource
.getParent()
.findMember(
resource.getName()
.replaceAll(
"(.*)" + Statistics.TSV_FILE_EXT, "$1" + Statistics.PROPERTIES_FILE_EXT)); //$NON-NLS-1$ //$NON-NLS-2$
Properties properties = new Properties();
properties.load(txtResource.getLocationURI().toURL().openStream());
Discovery discovery;
JavaDiscoveredProject benchmarkedProject = JavaBenchmarkFactory.eINSTANCE
.createJavaDiscoveredProject();
String storageKind = properties
.getProperty(DiscoverJavaModelFromJavaProjectEMFStat.STORAGE_KIND);
if (storageKind != null && storageKind.equals("CDO")) { //$NON-NLS-1$
CDODiscovery cdoDiscovery = JavaBenchmarkFactory.eINSTANCE
.createCDODiscovery();
discovery = cdoDiscovery;
cdoDiscovery.setVersion(properties
.getProperty(JavaDiscovererCDO.CDO_VERSION));
cdoDiscovery.setServerDescription(properties
.getProperty(JavaDiscovererCDO.CDO_SERVER_DESCRIPTION));
cdoDiscovery.setRevisedLruCapacity(new Integer(properties
.getProperty(JavaDiscovererCDO.REVISED_LRU_CAPACITY)));
cdoDiscovery.setCacheType(properties
.getProperty(JavaDiscovererCDO.CDO_CACHE_TYPE));
cdoDiscovery.setCurrentLruCapacity(new Integer(properties
.getProperty(JavaDiscovererCDO.CURRENT_LRU_CAPACITY)));
try {
cdoDiscovery.setInitTimeInSeconds(new Double(properties
.getProperty(Statistics.INIT_TIME))
/ Report.MINUTE_MS_RANGE);
} catch (Exception e) {
MoDiscoLogger.logError(e, Activator.getDefault());
IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID,
e.getMessage(), e);
errors.add(status);
}
} else {
discovery = BenchmarkFactory.eINSTANCE.createDiscovery();
}
benchmark.getProjects().add(benchmarkedProject);
benchmarkedProject.getDiscoveries().add(discovery);
benchmarkedProject
.setName(properties
.getProperty(DiscoverJavaModelFromJavaProjectEMFStat.JAVA_PROJECT_NAME));
discovery.setName(resource.getName().replaceAll(
"(.*)\\." + Statistics.TSV_FILE_EXT, "$1")); //$NON-NLS-1$ //$NON-NLS-2$
discovery.setMaxUsedMemoryInBytes(maxUsedMemory);
discovery.setMetaModelVariant(properties
.getProperty(DiscoverJavaModelFromJavaProjectEMFStat.MM_VARIANT));
discovery.setAlgorithmVariant(properties
.getProperty(DiscoverJavaModelFromJavaProjectEMFStat.ALGO_VARIANT));
discovery.setSaveTimeInSeconds(new Double(getValue(lastLine2,
Statistics.SAVE)) / Report.MINUTE_MS_RANGE);
discovery.setTotalExecutionTimeInSeconds(new Double(getValue(lastLine2,
Statistics.SINCEBEGIN)) / Report.MINUTE_MS_RANGE);
discovery
.setDiscovererClassName(properties
.getProperty(DiscoverJavaModelFromJavaProjectEMFStat.DISCOVERER_CLASS_NAME));
// configuration
// .setDicoveryDate(new Date(
// properties
// .getProperty(DiscoverJavaModelFromJavaProjectEMFStat.DISCOVERY_DATE)));
benchmark.setJvmMaxHeapInMiB(new Integer(properties.getProperty(
DiscoverJavaModelFromJavaProjectEMFStat.XMX).replaceAll(
"^([0-9]+).*", "$1"))); //$NON-NLS-1$//$NON-NLS-2$
rescaleDebugCode(discovery.getMaxUsedMemoryInBytes());
birt(file, benchmark, discovery);
}
}
this.statProject.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor());
} catch (Exception e) {
MoDiscoLogger.logError(e, Activator.getDefault());
IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.getMessage(), e);
errors.add(status);
}
}
modelResource.save(Collections.EMPTY_MAP);
if (errors.size() > 0) {
CoreException e = new CoreException(new MultiStatus(Activator.PLUGIN_ID, IStatus.ERROR,
errors.toArray(new IStatus[] {}), "", //$NON-NLS-1$
new Exception()));
MoDiscoLogger.logError(e, Activator.getDefault());
// throw e;
}
return benchmark;
}
private void birt(final IFile file, final Benchmark benchmark, final Discovery discovery) {
String diagramTitle = ""; //$NON-NLS-1$
if (discovery instanceof CDODiscovery) {
diagramTitle += "CDO "; //$NON-NLS-1$
}
if (discovery.getAlgorithmVariant() != null) {
diagramTitle += discovery.getAlgorithmVariant() + " "; //$NON-NLS-1$
}
if (discovery.getMetaModelVariant() != null) {
diagramTitle += discovery.getMetaModelVariant() + " "; //$NON-NLS-1$
}
if (discovery instanceof CDODiscovery) {
CDODiscovery cdoConfiguration = (CDODiscovery) discovery;
diagramTitle += "(" //$NON-NLS-1$
+ cdoConfiguration.getServerDescription() + ")"; //$NON-NLS-1$
}
ChartWithAxes chart = ChartWithAxesImpl.create();
chart.setDimension(ChartDimension.TWO_DIMENSIONAL_WITH_DEPTH_LITERAL);
chart.getPlot().setBackground(ColorDefinitionImpl.WHITE());
chart.getPlot().getClientArea().setBackground(ColorDefinitionImpl.WHITE());
chart.getLegend().setItemType(LegendItemType.SERIES_LITERAL);
chart.getLegend().setVisible(true);
chart.getTitle().getLabel().getCaption().setValue(diagramTitle);
// chart.getTitle().getLabel().getCaption().getFont().setSize(14);
// chart.getTitle().getLabel().getCaption().getFont().setName(FONT_NAME);
Axis xAxis = chart.getPrimaryBaseAxes()[0];
xAxis.getTitle().setCaption(TextImpl.create(Messages.Report_0));
xAxis.getTitle().setVisible(true);
// xAxis.getTitle().getCaption().setValue("xTitle");
NumberDataSet categoryValues = NumberDataSetImpl.create(this.map.get(-1));
Series xAxisSerie = SeriesImpl.create();
xAxisSerie.setDataSet(categoryValues);
SeriesDefinition xSeriesDefinition = SeriesDefinitionImpl.create();
xSeriesDefinition.getSeriesPalette().shift(1);
xAxis.getSeriesDefinitions().add(xSeriesDefinition);
xSeriesDefinition.getSeries().add(xAxisSerie);
Axis yAxis = chart.getPrimaryOrthogonalAxis(xAxis);
yAxis.getTitle().setVisible(true);
yAxis.getTitle().getCaption().setValue("MB"); //$NON-NLS-1$
// yAxis.getScale().setStep(1.0);
createYAxis(yAxis, "USED_MEMORY", ColorDefinitionImpl.BLACK()); //$NON-NLS-1$
createYAxis(yAxis, "DEBUG_CODE", ColorDefinitionImpl.BLUE()); //$NON-NLS-1$
Scale scale = ComponentFactory.eINSTANCE.createScale();
NumberDataElement dataElement = org.eclipse.birt.chart.model.data.DataFactory.eINSTANCE
.createNumberDataElement();
dataElement.setValue(discovery.getMaxUsedMemoryInBytes());
scale.setMax(dataElement);
NumberDataElement dataElement2 = org.eclipse.birt.chart.model.data.DataFactory.eINSTANCE
.createNumberDataElement();
dataElement2.setValue(0);
scale.setMin(dataElement2);
yAxis.setScale(scale);
// createYAxis(yAxis, "SINCEBEGIN (ms)", ColorDefinitionImpl.GREEN());
ResourceSet resourceSet = new ResourceSetImpl();
Resource resource = resourceSet.createResource(URI.createFileURI(file.getLocation()
.toString().replaceAll("(.*)" + Statistics.TSV_FILE_EXT, "$1xmi"))); //$NON-NLS-1$ //$NON-NLS-2$
resource.getContents().add(chart);
try {
resource.save(Collections.EMPTY_MAP);
PluginSettings ps = PluginSettings.instance();
IDeviceRenderer render = ps.getDevice("dv.PNG"); //$NON-NLS-1$
render.setProperty(IDeviceRenderer.FILE_IDENTIFIER, file.getLocation().toString()
.replaceAll("(.*)" + Statistics.TSV_FILE_EXT, "$1png")); //$NON-NLS-1$ //$NON-NLS-2$
Point size = new Point(Report.CHART_SIZE, Report.CHART_SIZE);
Bounds bounds = BoundsImpl.create(0, 0, size.x, size.y);
int resolution = render.getDisplayServer().getDpiResolution();
bounds.scale(Report.BOUNDS_SCALE_CONST / resolution);
Generator generator = Generator.instance();
GeneratedChartState state = generator.build(render.getDisplayServer(), chart, bounds,
null, null, null);
generator.render(render, state);
} catch (Exception ex) {
Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, ex.getMessage(), ex);
Activator.getDefault().getLog().log(status);
}
}
/**
* @param benchmark
* @throws IOException
*/
private static void generateHTML(final Benchmark benchmark, final File targetDirectory)
throws IOException {
new HtmlReport(benchmark, targetDirectory, new ArrayList<Object>()).doGenerate(null);
}
private void createYAxis(final Axis yAxis, final String columnName,
final ColorDefinition colorDefinition) {
LineSeries serie = (LineSeries) LineSeriesImpl.create();
serie.setSeriesIdentifier(columnName);
Integer indexx = this.titleMap.get(columnName);
Object values = this.map.get(indexx);
NumberDataSet dataSet = NumberDataSetImpl.create(values);
serie.setDataSet(dataSet);
serie.getMarkers().clear();
LineAttributes lineAttr = LineAttributesImpl.create(colorDefinition,
LineStyle.SOLID_LITERAL, 1);
serie.setLineAttributes(lineAttr);
Label label = LabelImpl.create();
label.setCaption(TextImpl.create(columnName));
label.setVisible(false);
serie.setLabel(label);
SeriesDefinition seriesDefinition = SeriesDefinitionImpl.create();
seriesDefinition.getSeries().add(serie);
yAxis.getSeriesDefinitions().add(seriesDefinition);
}
/**
*
*/
private void rescaleDebugCode(final long maxMemory) {
float coef = new Float(maxMemory) / Report.RESCALE_COEF;
ArrayList<Float> l = this.map.get(this.titleMap.get(Statistics.DEBUG_CODE));
ArrayList<Float> l2 = new ArrayList<Float>();
for (Float f : l) {
l2.add(f * coef);
}
this.map.put(this.titleMap.get(Statistics.DEBUG_CODE), l2);
}
private void addToSeries(final String line) {
this.index++;
this.map.get(-1).add(new Float(this.index));
String[] splits = line.split("\t"); //$NON-NLS-1$
for (int i = 0; i < splits.length; i++) {
Float f;
try {
f = new Float(splits[i]);
} catch (Exception e) {
f = new Float(0);
}
List<Float> serie = this.map.get(i);
serie.add(f);
}
}
private String getValue(final String line, final String columnName) {
try {
String[] splits = line.split("\t"); //$NON-NLS-1$
return splits[this.titleMap.get(columnName).intValue()];
} catch (Exception e) {
return ""; //$NON-NLS-1$
}
}
private void titleLine(final String line) {
String[] titles = line.split("\t"); //$NON-NLS-1$
this.titleMap.put("index", -1); //$NON-NLS-1$
this.map.put(-1, new ArrayList<Float>());
for (int i = 0; i < titles.length; i++) {
this.titleMap.put(titles[i], i);
this.map.put(i, new ArrayList<Float>());
}
}
}