| /******************************************************************************* |
| * Copyright (c) 2012, 2015 INRIA, and Mia-Software. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * Guillaume Doux (INRIA) - Initial API and implementation |
| * Grégoire Dupé (Mia-Software) - Bug 482672 - Benchmark command line interface |
| * Grégoire Dupé (Mia-Software) - Bug 482857 - Discoverer Benchmark Report : wrong namespaces |
| * Grégoire Dupé (Mia-Software) - Bug 483292 - [Benchmark] long must be used to store memory usage |
| * Grégoire Dupé (Mia-Software) - Bug 483400 - [Benchmark] The input size should be computable by the discoverer |
| * Grégoire Dupé (Mia-Software) - Bug 483639 - [Benchmark] Incorrect standard derivation computation |
| ******************************************************************************/ |
| package org.eclipse.modisco.infra.discovery.benchmark.core.internal.impl; |
| |
| import java.io.BufferedReader; |
| import java.io.FileReader; |
| import java.io.IOException; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.filesystem.EFS; |
| import org.eclipse.core.filesystem.IFileStore; |
| import org.eclipse.core.resources.IContainer; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IFolder; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IWorkspace; |
| 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.NullProgressMonitor; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.SubProgressMonitor; |
| 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.Factory.Registry; |
| import org.eclipse.emf.ecore.resource.ResourceSet; |
| import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; |
| import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; |
| import org.eclipse.emf.facet.util.core.Logger; |
| import org.eclipse.jdt.core.dom.Modifier; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.ISizeDiscoverer; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.Activator; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.MathUtils; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.Messages; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.api.IDiscovererBenchmarkDiscoverer; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.api.IDiscovererID; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.api.IEventNotifier; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.exported.IDiscovererList; |
| import org.eclipse.modisco.infra.discovery.benchmark.core.internal.exported.IProjectSet; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.Benchmark; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.BenchmarkFactory; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.Discovery; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.DiscoveryIteration; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.EndEvent; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.Event; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.EventType; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.File; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.MemoryMeasurement; |
| import org.eclipse.modisco.infra.discovery.benchmark.metamodel.internal.benchmark.Project; |
| import org.eclipse.modisco.infra.discovery.catalog.CatalogFactory; |
| import org.eclipse.modisco.infra.discovery.catalog.DiscovererDescription; |
| import org.eclipse.modisco.infra.discovery.catalog.DiscovererParameter; |
| import org.eclipse.modisco.infra.discovery.core.AbstractModelDiscoverer; |
| import org.eclipse.modisco.infra.discovery.core.IDiscoverer; |
| import org.eclipse.modisco.infra.discovery.core.IDiscoveryManager; |
| import org.eclipse.modisco.infra.discovery.core.annotations.Parameter; |
| import org.eclipse.modisco.infra.discovery.core.exception.DiscoveryException; |
| import org.eclipse.modisco.infra.discovery.launch.LaunchConfiguration; |
| import org.eclipse.modisco.infra.discovery.launch.LaunchFactory; |
| import org.eclipse.modisco.infra.discovery.launch.ParameterValue; |
| import org.eclipse.modisco.utils.core.internal.exported.SystemInfo; |
| import org.eclipse.osgi.util.NLS; |
| |
| /** |
| * Main entry point for the discoverer of benchmark |
| * @author Guillaume Doux |
| * |
| */ |
| public class DiscovererBenchmarkDiscoverer extends AbstractModelDiscoverer<IProjectSet> |
| implements IDiscovererBenchmarkDiscoverer { |
| |
| private static final String SAVE_OPERATION = "SaveOperation"; //$NON-NLS-1$ |
| private static final int INTERVAL = 1000; |
| private static final int MSINSEC = 1000; |
| private static final String CODE_EXTENSION = "java"; //$NON-NLS-1$ |
| public static final String ID = "org.eclipse.modisco.infra.discovery.benchmark.core.api.benchmarkdiscoverer"; //$NON-NLS-1$ |
| private static final long BYTEPERMB = 1024 * 1024; |
| |
| private IDiscovererID discovererID; |
| private int iterations; |
| private boolean measureMemoryUse; |
| private int memPollInterval; |
| private boolean generateHtml; |
| private URI htmlReportLoc; |
| private final List<MemoryMeasurement> memMeasurements; |
| private final List<Event> events; |
| private final ResourceSet rSet; |
| private EventAndMemoryRecorder recorder; |
| private IDiscovererList discoverers; |
| private String sizeDiscovererId; |
| |
| public DiscovererBenchmarkDiscoverer() { |
| super(); |
| this.discovererID = new DiscovererID(ID); |
| this.memPollInterval = 0; |
| this.memMeasurements = new LinkedList<MemoryMeasurement>(); |
| this.events = new LinkedList<Event>(); |
| this.rSet = new ResourceSetImpl(); |
| final Registry rFactoryRegistry = |
| this.rSet.getResourceFactoryRegistry(); |
| final Map<String, Object> extToFactoryMap = |
| rFactoryRegistry.getExtensionToFactoryMap(); |
| extToFactoryMap.put("xmi", new XMIResourceFactoryImpl()); //$NON-NLS-1$ |
| this.iterations = 1; |
| } |
| |
| protected IDiscovererList getDiscoverers() { |
| return this.discoverers; |
| } |
| |
| /** |
| * Setter for the list of discoverers, annotated with @Parameter set by the UI |
| * @param discos: the list of discoverers |
| */ |
| @Parameter(name = "DISCOVERER_LIST", description = "The list of discoverers.", requiresInputValue = true) |
| public void setDiscoverers(final IDiscovererList discos) { |
| this.discoverers = discos; |
| } |
| |
| /** |
| * Method launching the discovery process on all the discoverers X all the projects |
| * @param projects the set of projects to discover |
| * @param progressMonitor |
| * @return The benchmark model conforms to http://www.eclipse.org/modisco/infra/discovery/0.1.incubation/benchmark |
| * @throws DiscoveryException |
| */ |
| public Resource discoverBenchmark(final IProjectSet projects, |
| final IProgressMonitor progressMonitor) throws DiscoveryException { |
| this.recorder = |
| new EventAndMemoryRecorder(this.measureMemoryUse, |
| this.memPollInterval); |
| final int nbDiscoToDo = getIterations() * projects.getProjects().size() |
| * this.discoverers.getDiscoverers().size(); |
| progressMonitor.beginTask( |
| Messages.DiscovererBenchmarkDiscoverer_BenchmarkTaskName, |
| nbDiscoToDo); |
| final Benchmark benchmark = benchmarkInit(progressMonitor); |
| for (IProject project : projects.sortBySize().getProjects()) { |
| final Project projectDesc = createProjectDescription(project, |
| benchmark, progressMonitor); |
| for (Discovery discovery : this.discoverers) { |
| progressMonitor.subTask( |
| Messages.DiscovererBenchmarkDiscoverer_DiscoveryInitializationSubTask); |
| final String discovererId = discovery.getDiscovererId(); |
| final Discovery disco = createDiscovery(projectDesc, |
| discovery, benchmark); |
| AbstractModelDiscoverer<IProject> discoverer = null; |
| for (int i = 1; i <= this.iterations; i++) { |
| discoverer = preformIteration(progressMonitor, benchmark, |
| project, discovererId, disco, i); |
| } |
| postDiscoveryDiscoInit(disco, discoverer); |
| } |
| } |
| benchmark.setJvmMaxHeapInMiB(computeMaxMemoryUsage()); |
| save(benchmark, progressMonitor); |
| progressMonitor.worked(nbDiscoToDo); |
| if (isGenerateHtmlReport()) { |
| safeGenerateHtmlReport(progressMonitor, benchmark); |
| } |
| progressMonitor.done(); |
| return benchmark.eResource(); |
| } |
| |
| private AbstractModelDiscoverer<IProject> preformIteration( |
| final IProgressMonitor progressMonitor, final Benchmark benchmark, |
| final IProject project, final String discovererId, |
| final Discovery disco, final int iteration) { |
| final AbstractModelDiscoverer<IProject> discoverer = (AbstractModelDiscoverer<IProject>) |
| IDiscoveryManager.INSTANCE.createDiscovererImpl(discovererId); |
| final URI serializationLoc = getSerializationLoc(discoverer); |
| progressMonitor.subTask(NLS.bind( |
| Messages.DiscovererBenchmarkDiscoverer_ProjectDiscoveryIterationSubTask, |
| String.valueOf(getIterations()))); |
| final String suffix = String.format("%s_%s_i%s.xmi", //$NON-NLS-1$ |
| disco.getDiscovererId(), project.getName(), |
| String.valueOf(iteration)); |
| final URI uri = serializationLoc.appendSegment(suffix); |
| discoverer.setTargetURI(uri); |
| boolean failure = false; |
| final StringBuilder discoveryErrors = new StringBuilder(); |
| this.recorder.reset(); |
| if (IEventNotifier.class.isInstance(discoverer)) { |
| ((IEventNotifier) discoverer).addListener(this.recorder); |
| } |
| this.recorder.start(); |
| try { |
| if (discoverer.isApplicableTo(project)) { |
| final IProgressMonitor subProgressM = |
| new SubProgressMonitor(progressMonitor, 0); |
| discoverer.discoverElement(project, subProgressM); |
| } else { |
| final String message = String.format( |
| "Discoverer '%s' is not applicable on project '%s'.", //$NON-NLS-1$ |
| discovererId, project.getName()); |
| Logger.logError(message, Activator.getDefault()); |
| } |
| } catch (Exception e) { |
| failure = true; |
| discoveryErrors.append(e.getStackTrace().toString()); |
| final String message = String.format( |
| "Benchmark of discoverer %s fails on project '%s'", //$NON-NLS-1$ |
| discovererId, project.getName()); |
| Logger.logError(e, message, Activator.getDefault()); |
| } |
| this.recorder.stop(); |
| this.events.addAll(this.recorder.getEvents()); |
| this.events.addAll(this.recorder.getMemoryMeasurements()); |
| this.memMeasurements.addAll(this.recorder.getMemoryMeasurements()); |
| if (IEventNotifier.class.isInstance(discoverer)) { |
| ((IEventNotifier) discoverer).removeListener(this.recorder); |
| } |
| final DiscoveryIteration iterationDesc = |
| createDiscoveryIteration(this.recorder); |
| if (failure) { |
| iterationDesc.setDiscoveryErrors( |
| discoveryErrors.toString()); |
| } |
| disco.getIterations().add(iterationDesc); |
| save(benchmark, progressMonitor); |
| progressMonitor.worked(1); |
| return discoverer; |
| } |
| |
| private URI getSerializationLoc(final AbstractModelDiscoverer<IProject> discoverer) { |
| URI result; |
| if (discoverer.getTargetURI() == null) { |
| result = basicGetSerializationLoc(this); |
| } else { |
| result = basicGetSerializationLoc(discoverer); |
| } |
| return result; |
| } |
| |
| private Project createProjectDescription(final IProject project, |
| final Benchmark benchmark, final IProgressMonitor progressMonitor) |
| throws DiscoveryException { |
| progressMonitor.subTask( |
| Messages.DiscovererBenchmarkDiscoverer_ProjectInitializationSubTask); |
| final ISizeDiscoverer discoverer = (ISizeDiscoverer) |
| IDiscoveryManager.INSTANCE.createDiscovererImpl(this.sizeDiscovererId); |
| final Project projDesc = BenchmarkFactory.eINSTANCE.createProject(); |
| discoverer.discoverElement(project, new NullProgressMonitor()); |
| final double prjSize = discoverer.getSize(); |
| projDesc.setInputSize(prjSize); |
| final String prjUnit = discoverer.getUnit(); |
| projDesc.setInputSizeUnit(prjUnit); |
| projDesc.setName(project.getName()); |
| benchmark.getProjects().add(projDesc); |
| return projDesc; |
| } |
| |
| private void save(final Benchmark benchmark, |
| final IProgressMonitor progressMonitor) { |
| if (this.isTargetSerializationChosen()) { |
| try { |
| progressMonitor.subTask( |
| Messages.DiscovererBenchmarkDiscoverer_SavingBenchmarkDataSubTask); |
| saveTargetModel(benchmark); |
| } catch (IOException e) { |
| Logger.logError(e, "Failed to save the benchmark model.", //$NON-NLS-1$ |
| Activator.getDefault()); |
| } |
| } |
| } |
| |
| private static URI basicGetSerializationLoc( |
| final AbstractModelDiscoverer<?> discoverer) { |
| final URI targetURI = discoverer.getTargetURI(); |
| return targetURI.trimFileExtension(); |
| } |
| |
| /** |
| * Compute the size of the model in parameter (in number of model elements) |
| * @param targetModel |
| * @return the number of model elements |
| */ |
| private static long computeSize(final Resource targetModel) { |
| long size = 0; |
| if (targetModel == null) { |
| Logger.logWarning( |
| "Unable to compute the number of element of an unexisting model", //$NON-NLS-1$ |
| Activator.getDefault()); |
| } else { |
| for (final TreeIterator<EObject> iterator = |
| targetModel.getAllContents(); iterator.hasNext();) { |
| iterator.next(); |
| size++; |
| } |
| } |
| return size; |
| } |
| |
| private void safeGenerateHtmlReport(final IProgressMonitor progressMonitor, final Benchmark benchmark) { |
| try { |
| |
| generateHtmlReport(progressMonitor, benchmark); |
| } catch (Exception e) { |
| Logger.logError(e, "Report generation fail", Activator.getDefault()); //$NON-NLS-1$ |
| } |
| } |
| |
| /** |
| * launch the generation of the HTML report and the charts for the benchmark model in parameter |
| * @param parentMonitor |
| * @param benchmark |
| * @throws ReportUtilsException |
| * @throws CoreException |
| */ |
| private void generateHtmlReport(final IProgressMonitor parentMonitor, |
| final Benchmark benchmark) throws ReportUtilsException, CoreException { |
| parentMonitor.subTask( |
| Messages.DiscovererBenchmarkDiscoverer_GeneratingBenchmarkReportSubTask); |
| final IProgressMonitor progressMonitor = |
| new SubProgressMonitor(parentMonitor, 0); |
| //Get the output folder |
| URI targetURI = null; |
| if (this.getHtmlReportLocation() == null) { |
| targetURI = this.getTargetURI(); |
| } else { |
| targetURI = this.getHtmlReportLocation(); |
| } |
| if (targetURI == null) { |
| Logger.logWarning( |
| "The HTML_REPORT_LOCATION or the TARGET_URI parameter should not be null", //$NON-NLS-1$ |
| Activator.getDefault()); |
| return; |
| } |
| final IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| final IWorkspaceRoot wsRoot = workspace.getRoot(); |
| java.io.File file = null; |
| IFile iFile = null; |
| final String targetUriStr = targetURI.toString(); |
| if (targetURI.isPlatformResource()) { |
| final String pathStr = |
| targetUriStr.replaceAll("platform:/resource", ""); //$NON-NLS-1$//$NON-NLS-2$ |
| iFile = wsRoot.getFile(new Path(pathStr)); |
| iFile.getLocation().toFile(); |
| } else if (targetURI.isFile()) { |
| file = new java.io.File(java.net.URI.create(targetUriStr)); |
| } else { |
| final String message = String.format( |
| "The following target URI '%s' is not managed. 'platform:/resource' or 'file:/' are expected.", //$NON-NLS-1$ |
| targetURI.toString()); |
| throw new IllegalArgumentException(message); |
| } |
| final ArrayList<Object> arguments = new ArrayList<Object>(); |
| //Generation of the HTML report |
| ReportUtils.generateReport(benchmark, file, arguments, this.measureMemoryUse); |
| if (iFile != null) { |
| final IContainer location = iFile.getParent(); |
| location.refreshLocal(IResource.DEPTH_INFINITE, progressMonitor); |
| } |
| } |
| |
| /** |
| * Set the launch parameters of the {@link AbstractModelDiscoverer} in parameter with the content of the {@link Discovery} element |
| * @param disco {@link Discovery} |
| * @param discoverer {@link AbstractModelDiscoverer} (AbstractModelDiscoverer<IProject>) |
| */ |
| private void setLaunchParameter(final Discovery disco, |
| final AbstractModelDiscoverer<IProject> discoverer) { |
| final LaunchConfiguration launchConfig = |
| disco.getDiscovererLaunchConfiguration(); |
| if (launchConfig != null) { |
| for (ParameterValue pv : launchConfig.getParameterValues()) { |
| final DiscovererParameter parameter = pv.getParameter(); |
| final Object value = pv.getValue(); |
| if (value != null) { |
| try { |
| if (parameter.getSetter() == null) { |
| final Method setter = findSetter( |
| discoverer.getClass(), parameter.getId()); |
| parameter.setSetter(setter); |
| } |
| this.setValue(parameter, discoverer, value); |
| } catch (DiscoveryException e) { |
| Logger.logWarning(e, Activator.getDefault()); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * Find the setter of identifier id in the class clazz |
| * use java reflexion |
| * @param clazz |
| * @param paramId |
| * @return the setter |
| */ |
| private static Method findSetter( |
| final Class<? extends AbstractModelDiscoverer> clazz, |
| final String paramId) { |
| Method result = null; |
| for (Method method : clazz.getMethods()) { |
| if (method.isAnnotationPresent(Parameter.class)) { |
| final Parameter param = method.getAnnotation(Parameter.class); |
| if (param.name().equals(paramId) |
| && method.getReturnType().equals(void.class)) { |
| result = method; |
| } |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * method to set the values of parameters: extracted from DiscoveryManager |
| * (org.eclipse.modisco.infra.discovery.core.internal) |
| * |
| * @param parameter |
| * @param discoverer |
| * @param parameterValue |
| * @throws DiscoveryException |
| */ |
| private static void setValue(final DiscovererParameter parameter, |
| final IDiscoverer<?> discoverer, |
| final Object parameterValue) throws DiscoveryException { |
| try { |
| if (parameter.getField() != null |
| && Modifier.isPublic(parameter.getField().getModifiers())) { |
| parameter.getField().set(discoverer, parameterValue); |
| } else if (parameter.getSetter() != null |
| && Modifier.isPublic(parameter.getSetter().getModifiers())) { |
| parameter.getSetter().invoke(discoverer, parameterValue); |
| } else { |
| final String message = String.format( |
| "The discoverer '%s' does not implement public write access to the parameter '%s'", //$NON-NLS-1$ |
| discoverer.getClass(), |
| parameter.getId()); |
| throw new DiscoveryException(message); |
| } |
| } catch (IllegalArgumentException e) { |
| onInvokeException(parameter, parameterValue, e); |
| } catch (IllegalAccessException e) { |
| onInvokeException(parameter, parameterValue, e); |
| } catch (InvocationTargetException e) { |
| onInvokeException(parameter, parameterValue, e); |
| } |
| } |
| |
| private static void onInvokeException(final DiscovererParameter parameter, |
| final Object parameterValue, final Exception exception) |
| throws DiscoveryException { |
| final String message = String.format( |
| "Illegal parameter value for '%s' : %s", //$NON-NLS-1$ |
| parameter.getId(), parameterValue); |
| throw new DiscoveryException(message, exception); |
| } |
| |
| /** |
| * Save the benchmark model in an XMI file |
| * @param benchmark |
| * @throws IOException |
| */ |
| private void saveTargetModel(final Benchmark benchmark) throws IOException { |
| if ((this.getTargetURI() == null) && (this.getTargetModel() == null)) { |
| Logger.logWarning("The parameter TARGET_URI should not be empty", //$NON-NLS-1$ |
| Activator.getDefault()); |
| return; |
| } |
| Resource resource = benchmark.eResource(); |
| if (resource == null) { |
| URI resourceUri; |
| if (getTargetModel() == null) { |
| resourceUri = getTargetURI(); |
| } else { |
| resourceUri = getTargetModel().getURI(); |
| } |
| resource = this.rSet.createResource(resourceUri); |
| resource.getContents().add(benchmark); |
| } |
| final List<Event> eventsList = new ArrayList<Event>(); |
| final List<EventType> eventTypeList = new ArrayList<EventType>(); |
| for (Discovery discovery : benchmark.getDiscoveries()) { |
| for (DiscoveryIteration iteration : discovery.getIterations()) { |
| for (Event event : iteration.getEvents()) { |
| eventsList.add(event); |
| eventTypeList.add(event.getEventType()); |
| } |
| } |
| } |
| resource.getContents().addAll(eventTypeList); |
| this.setTargetModel(resource); |
| this.saveTargetModel(); |
| } |
| |
| /** |
| * Compute the maximum amount of memory used in the discovery |
| * @return max memory used |
| */ |
| private long computeMaxMemoryUsage() { |
| long max = 0; |
| for (MemoryMeasurement measure : this.memMeasurements) { |
| if (max < measure.getMemoryUsed()) { |
| max = measure.getMemoryUsed(); |
| } |
| } |
| return max; |
| } |
| |
| /** |
| * Initialize the benchmark model element with system information |
| * @return the model element |
| */ |
| private static Benchmark benchmarkInit(final IProgressMonitor progressMonitor) { |
| progressMonitor.subTask( |
| Messages.DiscovererBenchmarkDiscoverer_BenchmarkInitializationSubTask); |
| final Benchmark benchmark = BenchmarkFactory.eINSTANCE.createBenchmark(); |
| try { |
| final SystemInfo sysInfo = SystemInfo.getInstance(); |
| benchmark.setJvmMaxHeapInMiB(Runtime.getRuntime().maxMemory() / BYTEPERMB); |
| benchmark.setProcessorName(sysInfo.getProcName()); |
| benchmark.setProcessorDescription(sysInfo.getProcDescription()); |
| benchmark.setProcessorCount(sysInfo.getnProcessors()); |
| benchmark.setProcessorCacheSize(sysInfo.getProcCacheSize()); |
| benchmark.setSystemMemory(sysInfo.getMemory()); |
| benchmark.setOsName(sysInfo.getOsName()); |
| benchmark.setOsVersion(sysInfo.getOsVersion()); |
| benchmark.setOsArchitecture(sysInfo.getArch()); |
| } catch (IOException e) { |
| Logger.logError(e, |
| "Could not get system information for benchmark", //$NON-NLS-1$ |
| Activator.getDefault()); |
| } |
| return benchmark; |
| } |
| |
| /** |
| * Initialize the discovery model element before launching the associated |
| * discoverer |
| * |
| * @param projectDesc |
| * the model element for project that will be discovered |
| * @param disco |
| * the model element to initialize |
| * @param discovery |
| * the model element representing the information concerning the |
| * discovery in the launch configuration |
| * @param discoverer |
| * the real discoverer {@link AbstractModelDiscoverer} |
| * @param benchmark |
| * @param discovererId |
| * the discoverer id |
| */ |
| private Discovery createDiscovery(final Project projectDesc, |
| final Discovery discovery, final Benchmark benchmark) { |
| final String discovererId = discovery.getDiscovererId(); |
| final AbstractModelDiscoverer<IProject> discoverer = |
| (AbstractModelDiscoverer<IProject>) |
| IDiscoveryManager.INSTANCE.createDiscovererImpl(discovererId); |
| final Discovery disco = BenchmarkFactory.eINSTANCE.createDiscovery(); |
| disco.setProject(projectDesc); |
| disco.setName(discoverer.toString()); |
| disco.setDiscovererClassName(discoverer.getClass().getName()); |
| disco.setDiscovererId(discovererId); |
| final DiscovererDescription discoDesc = |
| CatalogFactory.eINSTANCE.createDiscovererDescription(); |
| final LaunchConfiguration discoLaunchConfig = |
| discovery.getDiscovererLaunchConfiguration(); |
| if (discoLaunchConfig != null) { |
| final LaunchConfiguration launchConfig = |
| LaunchFactory.eINSTANCE.createLaunchConfiguration(); |
| launchConfig.setSource(projectDesc.getName()); |
| launchConfig.setDiscoverer(discoDesc); |
| launchConfig.setOpenModelAfterDiscovery( |
| discoLaunchConfig.isOpenModelAfterDiscovery()); |
| for (ParameterValue paramValue : discoLaunchConfig.getParameterValues()) { |
| final ParameterValue newParamValue = |
| LaunchFactory.eINSTANCE.createParameterValue(); |
| newParamValue.setValue(paramValue.getValue()); |
| final DiscovererParameter param = |
| CatalogFactory.eINSTANCE.createDiscovererParameter(); |
| param.setDescription(paramValue.getParameter().getDescription()); |
| param.setDirection(paramValue.getParameter().getDirection()); |
| param.setDiscoverer(discoDesc); |
| param.setField(paramValue.getParameter().getField()); |
| param.setGetter(paramValue.getParameter().getGetter()); |
| param.setId(paramValue.getParameter().getId()); |
| param.setInitializer(paramValue.getParameter().getInitializer()); |
| param.setRequiredInput(paramValue.getParameter().isRequiredInput()); |
| param.setSetter(paramValue.getParameter().getSetter()); |
| param.setType(paramValue.getParameter().getType()); |
| newParamValue.setParameter(param); |
| launchConfig.getParameterValues().add(newParamValue); |
| } |
| disco.setDiscovererLaunchConfiguration(launchConfig); |
| } |
| if (discovery.getCopyOfDiscovererDescription() == null) { |
| discoDesc.setId(disco.getDiscovererId()); |
| discoDesc.setSourceType(projectDesc.getClass()); |
| discoDesc.setImplementationType(discoverer.getClass()); |
| } else { |
| discoDesc.setId(discovery.getCopyOfDiscovererDescription().getId()); |
| discoDesc.setImplementationBundle(discovery.getCopyOfDiscovererDescription().getImplementationBundle()); |
| discoDesc.setImplementationType(discovery.getCopyOfDiscovererDescription().getImplementationType()); |
| discoDesc.setSourceType(discovery.getCopyOfDiscovererDescription().getSourceType()); |
| } |
| disco.setCopyOfDiscovererDescription(discoDesc); |
| benchmark.getDiscoveries().add(disco); |
| setLaunchParameter(disco, discoverer); |
| return disco; |
| } |
| |
| /** |
| * Finalization of the initialization of the discovery model element after the effective discovery |
| * @param disco |
| * @param discoverer |
| */ |
| private void postDiscoveryDiscoInit(final Discovery disco, |
| final AbstractModelDiscoverer<IProject> discoverer) { |
| if (this.iterations > 0) { |
| final MathUtils.Resolver<DiscoveryIteration> discoTimeResolver = |
| new MathUtils.Resolver<DiscoveryIteration>() { |
| public double getValue(final DiscoveryIteration object) { |
| return object.getDiscoveryTimeInSeconds(); |
| } |
| }; |
| disco.setDiscoveryTimeAverageInSeconds(MathUtils.average( |
| disco.getIterations(), discoTimeResolver)); |
| disco.setExecutionTimeStandardDeviation(MathUtils.standardDeviation( |
| disco.getIterations(), discoTimeResolver)); |
| final MathUtils.Resolver<DiscoveryIteration> saveTimeResolver = |
| new MathUtils.Resolver<DiscoveryIteration>() { |
| public double getValue(final DiscoveryIteration object) { |
| return object.getSaveTimeInSeconds(); |
| } |
| }; |
| disco.setSaveTimeAverageInSeconds(MathUtils.average( |
| disco.getIterations(), saveTimeResolver)); |
| disco.setSaveTimeStandardDeviation(MathUtils.standardDeviation( |
| disco.getIterations(), saveTimeResolver)); |
| disco.setNumberOfModelElements(computeSize(discoverer.getTargetModel())); |
| IFileStore fileStore; |
| final URI targetURI = discoverer.getTargetURI(); |
| final String targetUriStr = targetURI.toString(); |
| try { |
| final IWorkspace workspace = ResourcesPlugin.getWorkspace(); |
| final IWorkspaceRoot wsRoot = workspace.getRoot(); |
| final IPath wsLoc = wsRoot.getLocation(); |
| final String wsLocStr = wsLoc.toString(); |
| final String locationString = "file://" + wsLocStr + targetUriStr; //$NON-NLS-1$ |
| final java.net.URI uri = java.net.URI.create(locationString); |
| fileStore = EFS.getStore(uri); |
| disco.setXmiSizeInBytes(fileStore.fetchInfo().getLength()); |
| } catch (Exception e) { |
| final String message = String.format( |
| "Could not get output model size (%s).", targetUriStr); //$NON-NLS-1$ |
| Logger.logError(e, message, Activator.getDefault()); |
| } |
| } |
| } |
| |
| /** |
| * Initialize a {@link DiscoveryIteration} after the discovery using the event and memory recorder |
| * @param recoreder {@link EventAndMemoryRecorder} |
| * @return the initialized discovery iteration |
| */ |
| private static DiscoveryIteration createDiscoveryIteration( |
| final EventAndMemoryRecorder recoreder) { |
| final DiscoveryIteration discoIter = |
| BenchmarkFactory.eINSTANCE.createDiscoveryIteration(); |
| discoIter.setDiscoveryDate(new Date()); |
| discoIter.setMaxUsedMemoryInBytes(recoreder.getMaxMemoryUsed()); |
| discoIter.getEvents().addAll(recoreder.getEvents()); |
| discoIter.setDiscoveryTimeInSeconds((recoreder.getStopTime() - recoreder.getStartTime()) / MSINSEC); |
| for (Event event : recoreder.getEvents()) { |
| if (event instanceof EndEvent |
| && event.getEventType().getName().equals(SAVE_OPERATION)) { |
| final double saveTime = event.getTime() |
| - ((EndEvent) event).getBeginning().getTime(); |
| discoIter.setSaveTimeInSeconds(saveTime / MSINSEC); |
| discoIter.setDiscoveryTimeInSeconds(discoIter.getDiscoveryTimeInSeconds() - discoIter.getSaveTimeInSeconds()); |
| } |
| } |
| discoIter.getMemoryMeasurements().addAll(recoreder.getMemoryMeasurements()); |
| return discoIter; |
| } |
| |
| /** |
| * Create the model elements for the projects and conaitned files to discover |
| * @param project the real project {@link IProject} |
| * @return the project model element {@link Project} |
| */ |
| private Project createBenchmarkProjectAndFiles(final IProject project) { |
| final Project proj = BenchmarkFactory.eINSTANCE.createProject(); |
| proj.setName(project.getName()); |
| try { |
| for (IResource res : project.members()) { |
| if (res instanceof IFolder) { |
| final List<File> files = createFiles((IFolder) res, new LinkedList<File>()); |
| proj.getFiles().addAll(files); |
| } else { |
| if (res instanceof IFile) { |
| final File file = createFile(res); |
| proj.getFiles().add(file); |
| } |
| } |
| } |
| if (proj.getFiles().isEmpty()) { |
| proj.setAverageFileSizeInBytes(0); |
| proj.setTotalSizeInBytes(0); |
| proj.setAverageLinesPerFile(0); |
| proj.setTotalLines(0); |
| } else { |
| long totalLineSize = 0; |
| long totalByteSize = 0; |
| for (File f : proj.getFiles()) { |
| totalLineSize += f.getLines(); |
| totalByteSize += f.getSizeInBytes(); |
| } |
| proj.setAverageFileSizeInBytes(totalByteSize / proj.getFiles().size()); |
| proj.setTotalSizeInBytes(totalByteSize); |
| proj.setAverageLinesPerFile(totalLineSize / getNumberOfSourceCodeFiles(proj)); |
| proj.setTotalLines(totalLineSize); |
| } |
| } catch (CoreException e) { |
| final String message = String.format( |
| "Could not get members of the project '%s'.", //$NON-NLS-1$ |
| project.getName()); |
| Logger.logError(e, |
| message, Activator.getDefault()); |
| } |
| return proj; |
| } |
| |
| /** |
| * Count the number of lines is source files. |
| * The source files are identified as having the value of the CODE_EXTENSION constant as extension |
| * @param proj the project to compute the number of lines |
| * @return the number of lines |
| */ |
| private static long getNumberOfSourceCodeFiles(final Project proj) { |
| int number = 0; |
| for (File file : proj.getFiles()) { |
| //only files having CODE_EXTENSION as extension are measured |
| if (file.getLines() == 0) { |
| number++; |
| } |
| } |
| return number; |
| } |
| |
| /** |
| * Initialize the files model elements {@link File} contained in a folder {@link IFolder} to discover. |
| * Recursive method, should be called initially on the project to discover |
| * @param folder |
| * @param files |
| * @return the list of initialized files {@link File} |
| * @throws CoreException |
| */ |
| private List<File> createFiles(final IFolder folder, final List<File> files) throws CoreException { |
| for (IResource res : folder.members()) { |
| if (res instanceof IFolder) { |
| final List<File> newFiles = |
| createFiles((IFolder) res, new LinkedList<File>()); |
| files.addAll(newFiles); |
| } else { |
| if (res instanceof IFile) { |
| final File file = createFile(res); |
| files.add(file); |
| } |
| } |
| } |
| return files; |
| } |
| |
| /** |
| * Initialize a file model element {@link File} from an eclipse resource {@link IResource} |
| * @param res the resource |
| * @return the initialized file |
| * @throws CoreException |
| */ |
| private static File createFile(final IResource res) throws CoreException { |
| final IFileStore fileStore = EFS.getStore(res.getLocationURI()); |
| final File file = BenchmarkFactory.eINSTANCE.createFile(); |
| file.setSizeInBytes(fileStore.fetchInfo().getLength()); |
| file.setFilepath(res.getFullPath().toString()); |
| file.setLines(getLineNumber(res)); |
| return file; |
| } |
| |
| /** |
| * Compute the number of lines in a file having as extension the value of the CODE_EXTENSION constant. |
| * @param res the file to compute the number of lines |
| * @return the number of line if source file 0 otherwise |
| */ |
| private static long getLineNumber(final IResource res) { |
| int lines = 0; |
| if (res == null) { |
| Logger.logWarning( |
| "Unable to compute the number of lines of an unexisting file", //$NON-NLS-1$ |
| Activator.getDefault()); |
| } else { |
| if (res.getFileExtension() != null |
| && res.getFileExtension().endsWith(CODE_EXTENSION)) { |
| try { |
| final java.io.File file = res.getLocation().toFile(); |
| final BufferedReader bReader = new BufferedReader( |
| new FileReader(file)); |
| for (lines = 0; bReader.readLine() != null; lines++); |
| bReader.close(); |
| } catch (Exception e) { |
| final String message = String.format( |
| "Counting the number of lines is '%s' failed ", //$NON-NLS-1$ |
| res.getName()); |
| Logger.logWarning(e, message, Activator.getDefault()); |
| } |
| } |
| } |
| return lines; |
| } |
| |
| /** |
| * @see AbstractModelDiscoverer#isApplicableTo(Object) |
| */ |
| public boolean isApplicableTo(final IProjectSet sources) { |
| boolean result = true; |
| for (IProject source : sources.getProjects()) { |
| result = result && source.getProject().isAccessible(); |
| } |
| return result; |
| } |
| |
| /** |
| * Launch the discovery by calling {@link DiscovererBenchmarkDiscoverer#discoverBenchmark(IProjectSet, IProgressMonitor)} |
| * @see AbstractModelDiscoverer#discoverElement(Object, IProgressMonitor) |
| */ |
| @Override |
| protected void basicDiscoverElement(final IProjectSet sources, final IProgressMonitor monitor) |
| throws DiscoveryException { |
| this.discoverBenchmark(sources, monitor); |
| } |
| |
| public void setDiscovererID(final IDiscovererID discoId) { |
| this.discovererID = discoId; |
| } |
| |
| public void setSizeDiscovererId(final String sizeDiscovererId) { |
| this.sizeDiscovererId = sizeDiscovererId; |
| } |
| |
| /** |
| * Setter for the number of iterations, annotated with @Parameter set by the UI |
| * @param it number of iterations |
| */ |
| @Parameter(name = "NUMBER_OF_ITERATIONS", description = "The number of iterations to do.", requiresInputValue = true) |
| public void setIterations(final int it) { |
| this.iterations = it; |
| } |
| |
| /** |
| * Setter for memory usage measure, annotated with @Parameter set by the UI |
| * @param measure true if the memory need to be measured |
| */ |
| @Parameter(name = "MEASURE_MEMORY_USAGE", description = "Tells if the memory usage should be measured or not.", requiresInputValue = true) |
| public void setMeasureMemoryUse(final boolean measure) { |
| this.measureMemoryUse = measure; |
| if (this.measureMemoryUse && this.memPollInterval == 0) { |
| this.memPollInterval = INTERVAL; |
| } |
| } |
| |
| /** |
| * Setter for the memory polling interval, annotated with @Parameter set by the UI |
| * @param memoryInterval memory polling interval in milliseconds |
| */ |
| @Parameter(name = "MEMORY_POLLING_INTERVAL", description = "The time interval between to memory measurement (default value is 1 sec)", requiresInputValue = false) |
| public void setMemoryPollingInterval(final int memoryInterval) { |
| this.memPollInterval = memoryInterval; |
| } |
| |
| /** |
| * Setter for the generation of an HTML report, annotated with @Parameter set by the UI |
| * @param generate true if an HTML report is wanted |
| */ |
| @Parameter(name = "GENERATE_HTML_REPORT", description = "Tells if a html report should be generated.", requiresInputValue = true) |
| public void setGenerateHtmlReport(final boolean generate) { |
| this.generateHtml = generate; |
| } |
| |
| /** |
| * Setter for the output model URI, annotated set by the UI |
| * @param the output model URI |
| */ |
| @Override |
| public void setTargetURI(final org.eclipse.emf.common.util.URI targetURI) { |
| super.setTargetURI(targetURI); |
| super.setTargetModel(this.rSet.createResource(targetURI)); |
| } |
| |
| @Override |
| @Parameter(name = "TARGET_URI") |
| public org.eclipse.emf.common.util.URI getTargetURI() { |
| return super.getTargetURI(); |
| } |
| |
| public IDiscovererID getDiscovererID() { |
| return this.discovererID; |
| } |
| |
| |
| public int getIterations() { |
| return this.iterations; |
| } |
| |
| public boolean isMeasureMemoryUse() { |
| return this.measureMemoryUse; |
| } |
| |
| public int getMemoryPollingInterval() { |
| return this.memPollInterval; |
| } |
| |
| public boolean isGenerateHtmlReport() { |
| return this.generateHtml; |
| } |
| |
| /** |
| * @return the htmlReportLocation |
| */ |
| public URI getHtmlReportLocation() { |
| return this.htmlReportLoc; |
| } |
| |
| /** |
| * Allow the selection of the HTML report location |
| * @param htmlReportLoc the htmlReportLocation to set |
| */ |
| @Parameter(name = "HTML_REPORT_LOCATION", |
| description = "Tells the location of the HTML report, should be set if GENERATE_HTML_REPORT is true", |
| requiresInputValue = false) |
| public void setHtmlReportLocation(final URI htmlReportUri) { |
| this.htmlReportLoc = htmlReportUri; |
| } |
| |
| } |