/* * Autopsy Forensic Browser * * Copyright 2014 Basis Technology Corp. * Contact: carrier <at> sleuthkit <dot> org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.sleuthkit.autopsy.diagnostics; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Random; import java.util.concurrent.ExecutionException; import javax.swing.JFrame; import javax.swing.SwingUtilities; import javax.swing.SwingWorker; import org.openide.util.NbBundle; import org.openide.windows.WindowManager; import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.datamodel.AbstractFile; import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.Image; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; public class PerformancePanel extends javax.swing.JDialog { /** * Creates new form PerformancePanel */ public PerformancePanel() { super((JFrame) WindowManager.getDefault().getMainWindow(), NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.title"), true); initComponents(); } /** * This method is called from within the constructor to initialize the form. * WARNING: Do NOT modify this code. The content of this method is always * regenerated by the Form Editor. */ @SuppressWarnings("unchecked") // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { jLabel1 = new javax.swing.JLabel(); imgReadLabel = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); dbReadLabel = new javax.swing.JLabel(); jLabel4 = new javax.swing.JLabel(); fileReadLabel = new javax.swing.JLabel(); jLabel3 = new javax.swing.JLabel(); cpuTimeLabel = new javax.swing.JLabel(); startButton = new javax.swing.JButton(); statusLabel = new javax.swing.JLabel(); jLabel5 = new javax.swing.JLabel(); setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); org.openide.awt.Mnemonics.setLocalizedText(jLabel1, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel1.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(imgReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.imgReadLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel2, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel2.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(dbReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.dbReadLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel4, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel4.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(fileReadLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.fileReadLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel3, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel3.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(cpuTimeLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.cpuTimeLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(startButton, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.startButton.text")); // NOI18N startButton.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { startButtonActionPerformed(evt); } }); org.openide.awt.Mnemonics.setLocalizedText(statusLabel, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.statusLabel.text")); // NOI18N org.openide.awt.Mnemonics.setLocalizedText(jLabel5, org.openide.util.NbBundle.getMessage(PerformancePanel.class, "PerformancePanel.jLabel5.text")); // NOI18N javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); getContentPane().setLayout(layout); layout.setHorizontalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGap(10, 10, 10) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(jLabel1) .addComponent(jLabel2) .addComponent(jLabel3)) .addGap(31, 31, 31) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(fileReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 228, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(dbReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(cpuTimeLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 284, javax.swing.GroupLayout.PREFERRED_SIZE) .addComponent(imgReadLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 237, javax.swing.GroupLayout.PREFERRED_SIZE)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addComponent(jLabel4) .addGap(0, 0, Short.MAX_VALUE)))) .addGroup(layout.createSequentialGroup() .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(startButton) .addComponent(jLabel5)) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) .addGroup(layout.createSequentialGroup() .addComponent(statusLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 508, javax.swing.GroupLayout.PREFERRED_SIZE) .addGap(0, 0, Short.MAX_VALUE)))) ); layout.setVerticalGroup( layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addGroup(layout.createSequentialGroup() .addContainerGap() .addComponent(jLabel5) .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel3) .addComponent(cpuTimeLabel)) .addGap(18, 18, 18) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) .addComponent(imgReadLabel) .addComponent(jLabel1)) .addGap(19, 19, 19) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel4) .addComponent(fileReadLabel)) .addGap(21, 21, 21) .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE) .addComponent(jLabel2) .addComponent(dbReadLabel)) .addGap(18, 18, 18) .addComponent(statusLabel) .addGap(9, 9, 9) .addComponent(startButton) .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) ); pack(); }// </editor-fold>//GEN-END:initComponents private void startButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_startButtonActionPerformed // TODO add your handling code here: startButton.setEnabled(false); SwingWorker<?, ?> worker = new PerformanceTestWorker(); worker.execute(); }//GEN-LAST:event_startButtonActionPerformed // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel cpuTimeLabel; private javax.swing.JLabel dbReadLabel; private javax.swing.JLabel fileReadLabel; private javax.swing.JLabel imgReadLabel; private javax.swing.JLabel jLabel1; private javax.swing.JLabel jLabel2; private javax.swing.JLabel jLabel3; private javax.swing.JLabel jLabel4; private javax.swing.JLabel jLabel5; private javax.swing.JButton startButton; private javax.swing.JLabel statusLabel; // End of variables declaration//GEN-END:variables class PerformanceTestWorker extends SwingWorker<Void, Void> { private long cpuStats; private long imgReadStats; private long dbStats; private long fileReadStats; @Override protected Void doInBackground() throws Exception { setCpuLabel(""); setImgLabel(""); setDbLabel(""); setFileReadLabel(""); doCpuTest(); doImgTest(); doFileReadTest(); doDbTest(); return null; } private void setCpuLabel(final String msg) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { cpuTimeLabel.setText(msg); } }); } private void setImgLabel(final String msg) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { imgReadLabel.setText(msg); } }); } private void setFileReadLabel(final String msg) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { fileReadLabel.setText(msg); } }); } private void setDbLabel(final String msg) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { dbReadLabel.setText(msg); } }); } private void setStatusMsg(final String msg) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { statusLabel.setText(msg); } }); } private void doCpuTest() { final String msg = NbBundle.getMessage(this.getClass(), "PerformancePanel.cpuTest.basemsg"); MessageDigest md; long start = new Date().getTime(); try { md = MessageDigest.getInstance("MD5"); // NON-NLS } catch (NoSuchAlgorithmException ex) { setCpuLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.cpuTest.cpuLabel.md5AlgNotFound.text")); return; } byte[] buf = new byte[256 * 1024]; long bytesRead = 0; for (int a = 0; a < 50; a++) { if (a % 10 == 0) { setStatusMsg(msg + " " + a * 100 / 50 + "%"); } for (byte b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) { Arrays.fill(buf, b); md.update(buf); bytesRead += buf.length; } } md.digest(); long end = new Date().getTime(); cpuStats = (bytesRead / (1024 * 1024)) / ((end - start) / 1000); setCpuLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.cpuTest.cpuLabel.MBHashedPerSec.text", cpuStats)); setStatusMsg(""); } private void doImgTest() { imgReadStats = 0; setStatusMsg( NbBundle.getMessage(this.getClass(), "PerformancePanel.imgTest.statusMsg.runningImgReadTest.text")); Case curCase; try { curCase = Case.getCurrentCase(); } catch (Exception e) { setImgLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.label.caseNotOpen.text")); setStatusMsg(""); return; } List<Content> dataSources; try { dataSources = curCase.getDataSources(); } catch (TskCoreException ex) { setImgLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.label.noImgInCase.text")); setStatusMsg(""); return; } Image image = null; for (Content c : dataSources) { if (c instanceof Image) { image = (Image) c; } } if (image == null) { setImgLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.label.noImgInCase.text")); setStatusMsg(""); return; } long start = new Date().getTime(); byte[] buf = new byte[4096]; long bytesRead = 0; // random starting point to prevent caching from effecting it Random rand = new Random(); long curOffset = rand.nextLong(); if (curOffset < 0) { curOffset *= -1; } curOffset = curOffset % (image.getSize() / 2); curOffset = 512 * ((curOffset + 511) / 512); //long curOffset = 0; while (bytesRead < 1000 * 1024 * 1024) { long read; try { read = image.read(buf, curOffset, buf.length); } catch (TskCoreException ex) { break; } if (read <= 0) { break; } bytesRead += read; curOffset += read; } long end = new Date().getTime(); long elapsed = (end - start) / 1000; if (elapsed > 0) { imgReadStats = (bytesRead / (1024 * 1024)) / elapsed; } else { imgReadStats = 0; } setImgLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.ImgTest.imgLabel.MBReadPerSec.text", imgReadStats, bytesRead)); setStatusMsg(""); } private void doFileReadTest() { fileReadStats = 0; // TODO: this is always true. Why display a "Skipped" label and then go on to run the test? if (true) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.FileReadTest.fileReadLabel.skipped.text")); } setStatusMsg(NbBundle.getMessage(this.getClass(), "PerformancePanel.FileReadTest.statusMsg.runningFileReadTest.text")); Case curCase; try { curCase = Case.getCurrentCase(); } catch (Exception e) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.label.caseNotOpen.text")); setStatusMsg(""); return; } List<Content> dataSources; try { dataSources = curCase.getDataSources(); } catch (TskCoreException ex) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.label.noImgInCase.text")); setStatusMsg(""); return; } Image image = null; for (Content c : dataSources) { if (c instanceof Image) { image = (Image) c; } } if (image == null) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.label.noImgInCase.text")); setStatusMsg(""); return; } File file = new File(image.getPaths()[0]); if (file.exists() == false) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.fileReadLabel.imgPathNotExist.text")); setStatusMsg(""); return; } FileReader fileReader; try { fileReader = new FileReader(file); } catch (FileNotFoundException ex) { setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.fileReadLabel.errMakeFileReader.text")); setStatusMsg(""); return; } long start = new Date().getTime(); // random starting point to prevent caching from effecting it // make RandomAccessFile instad /* * Random rand = new Random(); long curOffset = rand.nextLong(); if * (curOffset < 0) { curOffset *= -1; } curOffset = curOffset % * (file.length()); curOffset = 512 * ((curOffset + 511) / 512); try * { fileReader.skip(curOffset); } catch (IOException ex) { * setFileReadLabel("Error seeking: " + curOffset); return; } */ char[] buf = new char[4096]; int bytesRead = 0; while (bytesRead < 1000 * 1024 * 1024) { long read; try { read = fileReader.read(buf, 0, buf.length); } catch (IOException ex) { break; } if (read <= 0) { break; } bytesRead += read; } long end = new Date().getTime(); long elapsed = (end - start) / 1000; if (elapsed > 0) { fileReadStats = (bytesRead / (1024 * 1024)) / elapsed; } else { fileReadStats = 0; } setFileReadLabel( NbBundle.getMessage(this.getClass(), "PerformancePanel.ImgTest.fileReadLabel.MBReadPerSec.text", fileReadStats, bytesRead)); setStatusMsg(""); } private void doDbTest() { dbStats = 0; setStatusMsg(NbBundle.getMessage(this.getClass(), "PerformancePanel.dbTest.status.running")); Case curCase; try { curCase = Case.getCurrentCase(); } catch (Exception e) { setDbLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.label.caseNotOpen.text")); return; } try { SleuthkitCase tskCase = curCase.getSleuthkitCase(); long start = new Date().getTime(); List<AbstractFile> files = tskCase.findAllFilesWhere("obj_id < 50000"); // NON-NLS long end = new Date().getTime(); long elapsed = (end - start) / 1000; if (elapsed > 0) { dbStats = files.size() / elapsed; } else { dbStats = 0; } setDbLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.dbTest.dbLabel.recordsPerSec.text", dbStats)); } catch (TskCoreException ex) { setDbLabel(NbBundle.getMessage(this.getClass(), "PerformancePanel.dbTest.dbLabel.errPerformQuery.text")); } setStatusMsg(""); } @Override protected void done() { try { get(); } catch (InterruptedException | ExecutionException ex) { setStatusMsg(NbBundle.getMessage(this.getClass(), "PerformancePanel.done.statusMsg.err.text", ex.getMessage())); } startButton.setEnabled(true); } } }