blob: db2911ba57b9b69f389353a7645bf58f0baab790 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011, 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:
* Nicolas Bros (Mia-Software) - Bug 343155 - Java discoverer time benchmark
* Fabien Giquel (Mia-Software) - Bug 342856 - improve Discoverers implementation
*******************************************************************************/
package org.eclipse.modisco.java.discoverer.benchmark;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.IOWrappedException;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.modisco.infra.common.core.internal.utils.FileUtils;
import org.eclipse.modisco.infra.common.core.logging.MoDiscoLogger;
import org.eclipse.modisco.infra.discovery.benchmark.AveragedMultiDiscoveryBenchmark;
import org.eclipse.modisco.infra.discovery.benchmark.AveragedProjectDiscovery;
import org.eclipse.modisco.infra.discovery.benchmark.BenchmarkFactory;
import org.eclipse.modisco.infra.discovery.benchmark.Discovery;
import org.eclipse.modisco.infra.discovery.benchmark.ProjectDiscovery;
import org.eclipse.modisco.infra.discovery.core.AbstractModelDiscoverer;
import org.eclipse.modisco.infra.discovery.core.annotations.Parameter;
import org.eclipse.modisco.infra.discovery.core.exception.DiscoveryException;
import org.eclipse.modisco.java.discoverer.DiscoverJavaModelFromJavaProject;
import org.eclipse.modisco.java.discoverer.JavaDiscoveryConstants;
import org.eclipse.modisco.java.discoverer.benchmark.internal.SystemInfo;
import org.eclipse.modisco.java.discoverer.benchmark.javaBenchmark.JavaBenchmarkFactory;
import org.eclipse.modisco.java.discoverer.benchmark.javaBenchmark.JavaProject;
/** Runs a benchmark from a file containing a list of projects to benchmark */
public class JavaBenchmarkDiscoverer extends AbstractModelDiscoverer<IFile> {
private static final int BYTES_PER_MEBIBYTE = 1024 * 1024;
private static final double MILLISECONDS_PER_SECOND = 1000.0d;
public static final String INPUT_FILE_NAME = "javabenchconfig.txt"; //$NON-NLS-1$
public static final String OUTPUT_FILE_NAME = "javabench.xmi"; //$NON-NLS-1$
private static final Integer FLUSH_LIMIT = 65536;
private int numberOfIterations = 1;
@Parameter(name = "ITERATIONS", description = "The number of iterations to perform.")
public void setNumberOfIterations(final int iterations) {
this.numberOfIterations = iterations;
}
public int getNumberOfIterations() {
return this.numberOfIterations;
}
public boolean isApplicableTo(final IFile source) {
return source.exists() && JavaBenchmarkDiscoverer.INPUT_FILE_NAME.equals(source.getName());
}
@Override
protected void basicDiscoverElement(final IFile source, final IProgressMonitor monitor)
throws DiscoveryException {
IProject containingProject = source.getProject();
setDefaultTargetURI(URI.createPlatformResourceURI(
containingProject.getFullPath().append(JavaBenchmarkDiscoverer.OUTPUT_FILE_NAME)
.toString(), true));
createTargetModel();
List<IJavaProject> javaProjects = new ArrayList<IJavaProject>();
IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot();
try {
String input = FileUtils.readInputStream(source.getContents(), source.getCharset());
String[] lines = input.split("\\r?\\n"); //$NON-NLS-1$
for (String line : lines) {
line = line.trim();
if (line.length() == 0 || line.startsWith("#")) { //$NON-NLS-1$
continue;
}
IProject project = workspaceRoot.getProject(line);
if (!project.exists()) {
throw new DiscoveryException(
"Project \"" + project.getName() + "\" doesn't exist"); //$NON-NLS-1$//$NON-NLS-2$
}
final IJavaProject javaProject = JavaCore.create(project);
if (!javaProject.exists()) {
throw new DiscoveryException(
"\"" + project.getName() + "\" is not a valid Java project"); //$NON-NLS-1$ //$NON-NLS-2$
}
javaProjects.add(javaProject);
}
} catch (IOException e) {
throw new DiscoveryException("Error reading input file", e); //$NON-NLS-1$
} catch (CoreException e) {
throw new DiscoveryException("Error reading input file", e); //$NON-NLS-1$
}
AveragedMultiDiscoveryBenchmark benchmark = benchmarkJavaProjectsDiscovery(monitor,
javaProjects, this.numberOfIterations);
getTargetModel().getContents().add(benchmark);
}
public static AveragedMultiDiscoveryBenchmark benchmarkJavaProjectsDiscovery(
final IProgressMonitor monitor, final List<IJavaProject> javaProjects,
final int nIterations) throws DiscoveryException {
AveragedMultiDiscoveryBenchmark benchmark = BenchmarkFactory.eINSTANCE
.createAveragedMultiDiscoveryBenchmark();
benchmark
.setJvmMaxHeapInMiB((Runtime.getRuntime().maxMemory() / JavaBenchmarkDiscoverer.BYTES_PER_MEBIBYTE));
try {
SystemInfo systemInfo = SystemInfo.getInstance();
benchmark.setOsArchitecture(systemInfo.getArch());
benchmark.setOsName(systemInfo.getOsName());
benchmark.setOsVersion(systemInfo.getOsVersion());
benchmark.setProcessorCacheSize(systemInfo.getProcCacheSize());
benchmark.setProcessorCount(systemInfo.getnProcessors());
benchmark.setProcessorDescription(systemInfo.getProcDescription());
benchmark.setProcessorName(systemInfo.getProcName());
benchmark.setSystemMemory(systemInfo.getMemory());
} catch (IOException e) {
MoDiscoLogger.logError(e,
"Could not get system information for benchmark", Activator.getDefault()); //$NON-NLS-1$
}
final int nOperationsPerProject = 2;
// TODO: externalize
monitor.beginTask(
"Benchmarking java projects discovery", javaProjects.size() * nIterations * nOperationsPerProject); //$NON-NLS-1$
for (IJavaProject javaProject : javaProjects) {
testCanceled(monitor);
AveragedProjectDiscovery averagedProjectDiscovery = BenchmarkFactory.eINSTANCE
.createAveragedProjectDiscovery();
benchmark.getDiscoveries().add(averagedProjectDiscovery);
for (int i = 0; i < nIterations; i++) {
testCanceled(monitor);
ProjectDiscovery projectDiscovery = BenchmarkFactory.eINSTANCE
.createProjectDiscovery();
projectDiscovery.setName(javaProject.getElementName());
averagedProjectDiscovery.getOccurrences().add(projectDiscovery);
JavaProject javaBenchmarkedProject = JavaBenchmarkFactory.eINSTANCE
.createJavaProject();
projectDiscovery.getProjects().add(javaBenchmarkedProject);
javaBenchmarkedProject.setName(javaProject.getElementName());
testCanceled(monitor);
discoverJavaFilesInProject(javaProject, monitor, javaBenchmarkedProject,
projectDiscovery);
monitor.worked(1);
testCanceled(monitor);
benchmarkProjectDiscovery(javaProject, monitor, javaBenchmarkedProject,
projectDiscovery);
monitor.worked(1);
}
}
return benchmark;
}
protected static void testCanceled(final IProgressMonitor monitor) {
if (monitor.isCanceled()) {
throw new OperationCanceledException();
}
}
protected static void discoverJavaFilesInProject(final IJavaProject javaProject,
final IProgressMonitor monitor, final JavaProject javaBenchmarkedProject,
final Discovery discovery) throws DiscoveryException {
try {
// TODO: externalize
monitor.subTask("Visiting " + javaProject.getElementName()); //$NON-NLS-1$
javaProject.getProject().accept(new IResourceVisitor() {
public boolean visit(final IResource resource) throws CoreException {
testCanceled(monitor);
if (resource instanceof IFile) {
IFile iFile = (IFile) resource;
if ("java".equals(iFile.getFileExtension())) { //$NON-NLS-1$
// IJavaElement javaElement =
// javaProject.findElement(path);
// if (javaElement instanceof ICompilationUnit) {
// ICompilationUnit compilationUnit =
// (ICompilationUnit) javaElement;
org.eclipse.modisco.infra.discovery.benchmark.File file = BenchmarkFactory.eINSTANCE
.createFile();
javaBenchmarkedProject.getFiles().add(file);
file.setFilepath(iFile.getFullPath().removeFirstSegments(1)
.toPortableString());
String input;
try {
input = FileUtils.readInputStream(iFile.getContents(),
iFile.getCharset());
} catch (IOException e) {
throw new CoreException(new Status(IStatus.ERROR,
Activator.PLUGIN_ID, 0, "Error reading file " //$NON-NLS-1$
+ iFile.getFullPath().toString(), e));
}
String[] lines = input.split("\\r?\\n"); //$NON-NLS-1$
file.setLines(lines.length + 1);
file.setSizeInBytes(iFile.getLocation().toFile().length());
// }
}
}
return true;
}
});
} catch (CoreException e) {
throw new DiscoveryException("Error visiting project", e); //$NON-NLS-1$
}
}
protected static void benchmarkProjectDiscovery(final IJavaProject javaProject,
final IProgressMonitor monitor, final JavaProject javaBenchmarkedProject,
final Discovery discovery) {
testCanceled(monitor);
System.gc();
long beforeDiscovery = System.currentTimeMillis();
String error = null;
DiscoverJavaModelFromJavaProject discoverer = null;
try {
discoverer = new DiscoverJavaModelFromJavaProject();
discoverer.discoverElement(javaProject, monitor);
} catch (Throwable e) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
error = byteArrayOutputStream.toString();
}
discovery.setDiscoveryError(error);
long discoveryTime = (System.currentTimeMillis() - beforeDiscovery);
long totalMemory = Runtime.getRuntime().totalMemory();
discovery.setDicoveryDate(new Date());
discovery.setDiscovererClassName(DiscoverJavaModelFromJavaProject.class.getName());
discovery.setDiscovererId(DiscoverJavaModelFromJavaProject.ID
+ " v" + Activator.getDefault().getBundle().getVersion().toString()); //$NON-NLS-1$
discovery.setMaxUsedMemoryInBytes(totalMemory);
discovery
.setTotalExecutionTimeInSeconds((discoveryTime / JavaBenchmarkDiscoverer.MILLISECONDS_PER_SECOND));
if (discoverer != null) {
Resource targetModel = discoverer.getTargetModel();
discovery.setNumberOfModelElements(countModelElements(targetModel));
IProject project = javaProject.getProject();
String xmiFilename = project.getName() + JavaDiscoveryConstants.JAVA_MODEL_FILE_SUFFIX;
IPath targetXMIPath = project.getFullPath().append(xmiFilename);
targetModel.setURI(URI.createPlatformResourceURI(targetXMIPath.toString(), true));
testCanceled(monitor);
long beforeSave = System.currentTimeMillis();
try {
save(targetModel);
} catch (Throwable e) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
e.printStackTrace(new PrintWriter(byteArrayOutputStream, true));
error = byteArrayOutputStream.toString();
discovery.setDiscoveryError(error);
return;
}
long saveTime = System.currentTimeMillis() - beforeSave;
File xmiFile = project.getLocation().append(xmiFilename).toFile();
discovery.setXmiSizeInBytes(xmiFile.length());
discovery
.setSaveTimeInSeconds((saveTime / JavaBenchmarkDiscoverer.MILLISECONDS_PER_SECOND));
}
}
private static void save(final Resource targetModel) throws IOException {
if (targetModel != null) {
Map<String, Object> options = new HashMap<String, Object>();
options.put(XMLResource.OPTION_FLUSH_THRESHOLD, JavaBenchmarkDiscoverer.FLUSH_LIMIT);
options.put(XMLResource.OPTION_USE_FILE_BUFFER, Boolean.TRUE);
try {
targetModel.save(options);
} catch (IOWrappedException e) {
// TODO this is a temporary fix for Bug 323247
if (e.getCause() != null && (e.getCause() instanceof CoreException)) {
MoDiscoLogger.logWarning(e,
"XMI serialization has failed on '" + targetModel.getURI() //$NON-NLS-1$
+ "'. Trying again without File Buffer.", //$NON-NLS-1$
Activator.getDefault());
options.clear();
targetModel.save(options);
MoDiscoLogger.logInfo("XMI serialization is done for " + targetModel.getURI(), //$NON-NLS-1$
Activator.getDefault());
} else {
throw e;
}
}
}
}
protected static long countModelElements(final Resource targetModel) {
TreeIterator<EObject> allContents = targetModel.getAllContents();
long nElements = 0;
while (allContents.hasNext()) {
allContents.next();
nElements++;
}
return nElements;
}
}