/* * Carrot2 project. * * Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński. * All rights reserved. * * Refer to the full license file "carrot2.LICENSE" * in the root folder of the repository checkout or at: * http://www.carrot2.org/carrot2.LICENSE */ package org.carrot2.workbench.core.ui; import java.util.Locale; import org.carrot2.workbench.core.helpers.Utils; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.jobs.*; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.widgets.*; import org.eclipse.ui.internal.browser.WebBrowserEditor; import org.eclipse.ui.internal.browser.WebBrowserEditorInput; import org.eclipse.ui.part.Page; import org.eclipse.ui.progress.UIJob; /** * A single benchmark view page is associated with a given editor (and hence with the * given input and algorithm). */ @SuppressWarnings("restriction") final class BenchmarkViewPage extends Page { private final static String START_TEXT = "Start"; private final static String STOP_TEXT = "Stop"; /** The configuration we are benchmarking. */ private final SearchEditor editor; /** Main page control. */ private Control mainControl; private Label avgTimeLabel; private Label minTimeLabel; private Label maxTimeLabel; private Label stddevLabel; private Label statusLabel; private Button startButton; private ProgressBar progressBar; /** * Benchmarking job is part of Eclipse's infrastructure. */ private BenchmarkJob benchmarkJob; /** Parent benchmark view. */ private final BenchmarkView benchmarkView; /** * Update benchmarking job results. */ private Job benchmarkStatusUpdateJob = new UIJob("Benchmark update") { { this.setPriority(Job.SHORT); this.setSystem(true); } @Override public IStatus runInUIThread(IProgressMonitor monitor) { if (benchmarkJob != null) { updateBenchmark(benchmarkJob.statistics); this.schedule(1000); } return Status.OK_STATUS; } }; /** * Job tracking. */ private IJobChangeListener jobListener = new JobChangeAdapter() { @Override public void done(IJobChangeEvent ijobchangeevent) { Display.getDefault().asyncExec(new Runnable() { public void run() { updateBenchmark(benchmarkJob.statistics); endBenchmark(); } }); } }; /** * Start benchmarking job. */ private void startBenchmark() { assert Display.getCurrent() != null; startButton.setText(STOP_TEXT); benchmarkJob = new BenchmarkJob( editor.getSearchResult().getInput(), benchmarkView.getCurrentSettings()); updateBenchmark(benchmarkJob.statistics); benchmarkJob.addJobChangeListener(jobListener); benchmarkJob.schedule(); benchmarkStatusUpdateJob.schedule(); } /** * Update benchmark GUI state. */ private void updateBenchmark(BenchmarkStatistics statistics) { assert Display.getCurrent() != null; if (statistics.round == 0) { this.progressBar.setMaximum(statistics.benchmarkRounds + statistics.warmupRounds); this.progressBar.setMinimum(0); this.progressBar.setSelection(0); avgTimeLabel.setText(""); stddevLabel.setText(""); minTimeLabel.setText(""); maxTimeLabel.setText(""); statusLabel.setText("waiting for data"); } else { this.progressBar.setSelection(statistics.round); avgTimeLabel.setText(formatSeconds(statistics.avg)); stddevLabel.setText(formatSeconds(statistics.stdDev)); minTimeLabel.setText(formatSeconds(statistics.min)); maxTimeLabel.setText(formatSeconds(statistics.max)); String status; if (statistics.round < statistics.warmupRounds) { status = "warmup"; } else if (statistics.round == statistics.warmupRounds + statistics.benchmarkRounds) { status = "done"; } else { status = "benchmark"; } statusLabel.setText(String.format("Round %d (%s)", statistics.round, status)); } } /* * */ private String formatSeconds(double v) { return String.format(Locale.ENGLISH, "%.03f sec.", v / 1000.0); } /** * Cleans up after a benchmarking job. */ private void endBenchmark() { assert Display.getCurrent() != null; try { if (benchmarkJob.settings.openLogsInEditor) { getSite().getWorkbenchWindow().getActivePage().openEditor( new WebBrowserEditorInput( benchmarkJob.logFile.toURI().toURL()), WebBrowserEditor.WEB_BROWSER_EDITOR_ID); } } catch (Exception e) { Utils.logError(e, true); } benchmarkJob = null; startButton.setText(START_TEXT); startButton.setEnabled(true); } /* * */ public BenchmarkViewPage(SearchEditor editor, BenchmarkView benchmarkView) { this.editor = editor; this.benchmarkView = benchmarkView; } /* * */ @Override public void createControl(Composite parent) { this.mainControl = createBenchmarkPanel(parent); } /** * Create benchmark panel component. */ private Control createBenchmarkPanel(Composite parent) { final Composite panel = new Composite(parent, SWT.NONE); panel.setLayout( GridLayoutFactory.fillDefaults() .numColumns(1) .margins(0, 0).create()); panel.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); // Progress bar | start/stop button final Composite row1 = new Composite(panel, SWT.NONE); row1.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); row1.setLayout(GridLayoutFactory.fillDefaults() .numColumns(2).margins(0, 0).create()); progressBar = new ProgressBar(row1, SWT.HORIZONTAL | SWT.SMOOTH); progressBar.setMinimum(0); progressBar.setMaximum(100); progressBar.setSelection(0); progressBar.setLayoutData(GridDataFactory.fillDefaults().grab(true, false).create()); startButton = new Button(row1, SWT.PUSH); startButton.setText(START_TEXT); startButton.setLayoutData(GridDataFactory.fillDefaults().create()); startButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent selectionevent) { if (benchmarkJob == null) { startBenchmark(); } else { benchmarkJob.cancel(); startButton.setEnabled(false); } } }); // On-line reports and statistics. final Composite row2 = new Composite(panel, SWT.NONE); row2.setLayoutData(GridDataFactory.fillDefaults().create()); row2.setLayout(GridLayoutFactory.fillDefaults().numColumns(4).margins(0, 0).create()); statusLabel = addLabelOneColumn(row2, "Status:"); avgTimeLabel = addLabelTwoColumns(row2, "Avg time:"); stddevLabel = addLabelTwoColumns(row2, "Std dev:"); minTimeLabel = addLabelTwoColumns(row2, "Min time:"); maxTimeLabel = addLabelTwoColumns(row2, "Max time:"); return panel; } /* * Adds a label-value pair to a composite (spans two columns). */ private Label addLabelTwoColumns(Composite c, String text) { final Label lb1 = new Label(c, SWT.LEAD); lb1.setText(text); lb1.setLayoutData(GridDataFactory.swtDefaults().create()); final Label lb2 = new Label(c, SWT.LEAD); lb2.setText(""); lb2.setLayoutData(GridDataFactory.swtDefaults().align(SWT.FILL, SWT.FILL).grab(true, false).create()); return lb2; } /* * Adds a label-value pair to a composite (spans four columns). */ private Label addLabelOneColumn(Composite c, String text) { final Label lb1 = new Label(c, SWT.LEAD); lb1.setText(text); lb1.setLayoutData(GridDataFactory.swtDefaults().create()); final Label lb2 = new Label(c, SWT.LEAD); lb2.setText(""); lb2.setLayoutData(GridDataFactory .swtDefaults().span(3, 1) .align(SWT.FILL, SWT.FILL).grab(true, false).create()); return lb2; } /* * */ @Override public Control getControl() { return mainControl; } /* * */ @Override public void setFocus() { this.startButton.setFocus(); } }