/* * Copyright (C) 2015 CS SI * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.smart.configurator.ui; import com.bc.ceres.core.ProgressMonitor; import com.bc.ceres.core.SubProgressMonitor; import com.bc.ceres.core.VirtualDir; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.gpf.Operator; import org.esa.snap.core.gpf.common.WriteOp; import org.esa.snap.core.gpf.internal.OperatorContext; import org.esa.snap.core.gpf.internal.OperatorExecutor; import org.esa.snap.core.gpf.internal.OperatorProductReader; import org.esa.snap.core.gpf.ui.DefaultSingleTargetProductDialog; import org.esa.snap.core.gpf.ui.TargetProductSelectorModel; import org.esa.snap.core.util.SystemUtils; import org.esa.snap.rcp.actions.file.SaveProductAsAction; import org.esa.snap.rcp.util.ProgressHandleMonitor; import org.esa.snap.smart.configurator.Benchmark; import org.esa.snap.smart.configurator.BenchmarkSingleCalculus; import org.esa.snap.smart.configurator.ConfigurationOptimizer; import org.esa.snap.smart.configurator.PerformanceParameters; import org.esa.snap.smart.configurator.StoredGraphOp; import org.esa.snap.ui.AppContext; import org.netbeans.api.progress.ProgressUtils; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.util.Cancellable; import javax.media.jai.JAI; import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; import java.awt.*; import java.io.File; import java.nio.file.Paths; import java.util.List; /** * Dialog to launch performance parameters benchmark. * * @author Manuel Campomanes */ public class BenchmarkDialog extends DefaultSingleTargetProductDialog { /** * Benchmark calculus model */ private Benchmark benchmarkModel; /** * Parent panel */ private PerformancePanel perfPanel; /** * Constructor * * @param perfPanel Parent JPanel * @param operatorName Operator name * @param benchmarkModel Benchmark model * @param appContext Application context */ public BenchmarkDialog(PerformancePanel perfPanel, String operatorName, Benchmark benchmarkModel, AppContext appContext) { super(operatorName, appContext, "Benchmark " + operatorName, null, false); this.benchmarkModel = benchmarkModel; this.getJDialog().setModal(true); this.perfPanel = perfPanel; } protected void executeOperator(Product targetProduct, ProgressHandleMonitor pm) throws Exception { final TargetProductSelectorModel model = getTargetProductSelector().getModel(); //To avoid a nullPointerException in model.getProductFile() if(model.getProductName()==null) { model.setProductName(targetProduct.getName()); } Operator execOp = null; if (targetProduct.getProductReader() instanceof OperatorProductReader) { final OperatorProductReader opReader = (OperatorProductReader) targetProduct.getProductReader(); Operator operator = opReader.getOperatorContext().getOperator(); boolean autoWriteDisabled = operator.getSpi().getOperatorDescriptor().isAutoWriteDisabled(); if (autoWriteDisabled) { execOp = operator; } } if (execOp == null) { WriteOp writeOp = new WriteOp(targetProduct, model.getProductFile(), model.getFormatName()); writeOp.setDeleteOutputOnFailure(true); writeOp.setWriteEntireTileRows(true); writeOp.setClearCacheAfterRowWrite(false); execOp = writeOp; } SubProgressMonitor pm2 = (SubProgressMonitor) SubProgressMonitor.create(pm, 95); //execute if(execOp.canComputeTile() || execOp.canComputeTileStack()) { final OperatorExecutor executor = OperatorExecutor.create(execOp); executor.execute(pm2); } else { execOp.execute(pm2); } pm2.done(); } @Override protected void onApply() { BenchmarkExecutor executor = new BenchmarkExecutor(); //launch processing with a progress bar ProgressHandleMonitor pm = ProgressHandleMonitor.create("Running benchmark", executor); executor.setProgressHandleMonitor(pm); ProgressUtils.runOffEventThreadWithProgressDialog(executor, "Benchmarking....", pm.getProgressHandle(), true, 50, 1000); } private class BenchmarkExecutor implements Runnable, Cancellable { ProgressHandleMonitor progressHandleMonitor = null; BenchmarkSingleCalculus currentBenchmarkSingleCalcul = null; private boolean canceled = false; private void setProgressHandleMonitor(ProgressHandleMonitor progressHandleMonitor) { this.progressHandleMonitor = progressHandleMonitor; } @Override public boolean cancel() { //load old params (before benchmark) benchmarkModel.loadBenchmarkPerfParams(currentBenchmarkSingleCalcul); canceled = true; return true; } @Override public void run() { canceled = false; if (progressHandleMonitor == null) { throw new IllegalStateException("Progress Handle Monitor not set"); } //temporary directory for benchmark String tmpdirPath = Paths.get(SystemUtils.getCacheDir().toString(), "snap-benchmark-tmp").toString(); appContext.getPreferences().setPropertyString(SaveProductAsAction.PREFERENCES_KEY_LAST_PRODUCT_DIR, tmpdirPath); //add current performance parameters to benchmark PerformanceParameters currentPerformanceParameters = ConfigurationOptimizer.getInstance().getActualPerformanceParameters(); currentBenchmarkSingleCalcul = new BenchmarkSingleCalculus( /*currentPerformanceParameters.getDefaultTileSize(), */currentPerformanceParameters.getTileHeight(),currentPerformanceParameters.getTileWidth(), currentPerformanceParameters.getCacheSize(), currentPerformanceParameters.getNbThreads()); if (!benchmarkModel.isAlreadyInList(currentBenchmarkSingleCalcul)) { benchmarkModel.addBenchmarkCalcul(currentBenchmarkSingleCalcul); } try { progressHandleMonitor.beginTask("Benchmark running... ", benchmarkModel.getBenchmarkCalculus().size() * 100); List<BenchmarkSingleCalculus> benchmarkSingleCalculusList = benchmarkModel.getBenchmarkCalculus(); int executionOrder = 0; for (BenchmarkSingleCalculus benchmarkSingleCalcul : benchmarkSingleCalculusList) { /*progressHandleMonitor.getProgressHandle().progress( String.format("Benchmarking ( tile size:%s , cache size:%d , nb threads:%d )", benchmarkSingleCalcul.getDimensionString(), benchmarkSingleCalcul.getCacheSize(), benchmarkSingleCalcul.getNbThreads()));*/ progressHandleMonitor.getProgressHandle().progress( String.format("Benchmarking ( cache size:%d , nb threads:%d )", benchmarkSingleCalcul.getCacheSize(), benchmarkSingleCalcul.getNbThreads())); final Product targetProduct; //load performance parameters for current benchmark benchmarkModel.loadBenchmarkPerfParams(benchmarkSingleCalcul); //processing start time long startTime = System.currentTimeMillis(); try { targetProduct = createTargetProduct(); } catch (Throwable t) { handleInitialisationError(t); throw t; } if (targetProduct == null) { throw new NullPointerException("Target product is null."); } //When the source product is read at the beginning, a preferred tile size is selected (tipically, the tile size of the properties). //There are some operators which do not use the properties for setting the tile size of the product and they use directly the tile size of the inputs. //Since the inputs are loaded only one time, the first tile size is always used. //In the line below, we re-write that preferred tile size in order to generate the output with the benchmark value. //TODO review because getTile from benchmarkSingleCalcul could be null or *... //targetProduct.setPreferredTileSize(new Dimension(Integer.parseInt(benchmarkSingleCalcul.getTileWidth()),Integer.parseInt(benchmarkSingleCalcul.getTileHeight()))); executeOperator(targetProduct, progressHandleMonitor); //save execution time long endTime = System.currentTimeMillis(); benchmarkSingleCalcul.setExecutionTime(endTime - startTime); benchmarkSingleCalcul.setExecutionOrder(executionOrder); executionOrder++; SystemUtils.LOG.fine(String.format("Start time: %d, end time: %d, diff: %d", startTime, endTime, endTime - startTime)); // we remove all tiles //TODO cambiar, esto solo funciona si es cache in memery, pero no si es en file JAI.getDefaultInstance().getTileCache().flush(); } progressHandleMonitor.done(); } catch (Exception ex) { SystemUtils.LOG.severe("Could not perform benchmark: " + ex.getMessage()); } finally { //load old params (before benchmark) benchmarkModel.loadBenchmarkPerfParams(currentBenchmarkSingleCalcul); //delete benchmark TMP directory VirtualDir.deleteFileTree(new File(tmpdirPath)); } managePostBenchmark(); } private void managePostBenchmark() { if (!canceled) { //sort benchmark results and return the fastest BenchmarkSingleCalculus bestBenchmarkSingleCalcul = benchmarkModel.getFasterBenchmarkSingleCalculus(); //load fastest params? benchmarkModel.loadBenchmarkPerfParams(bestBenchmarkSingleCalcul); showResults(); //update parent panel with best values perfPanel.updatePerformanceParameters(bestBenchmarkSingleCalcul); } close(); } private void showResults() { // table model class BenchmarkTableModel extends AbstractTableModel { //final String[] columnNames = benchmarkModel.getColumnsNames(); //final int[][] data = benchmarkModel.getRowsToShow(); final String[] columnNames = benchmarkModel.getColumnsNamesWithoutTileSize(); final int[][] data = benchmarkModel.getRowsToShowWhitoutTileSize(); @Override public Class getColumnClass(int column) { return Integer.class; } public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.length; } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return data[row][col]; } } BenchmarkTableModel tableModel = new BenchmarkTableModel(); JTable table = new JTable(tableModel); // For sorting TableRowSorter<TableModel> rowSorter = new TableRowSorter<TableModel>(tableModel); table.setRowSorter(rowSorter); DefaultTableCellRenderer tcr = new DefaultTableCellRenderer(); tcr.setHorizontalAlignment(SwingConstants.CENTER); table.getColumnModel().getColumn(table.getColumnCount() - 1).setCellRenderer(tcr); JPanel panel = new JPanel(new BorderLayout(4, 4)); JScrollPane panelTable = new JScrollPane(table); panel.add(panelTable, BorderLayout.CENTER); NotifyDescriptor d = new NotifyDescriptor(panel, "Benchmark results", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE, null, null); DialogDisplayer.getDefault().notify(d); } } }