From 15de072e71273debb15dfbf202523b4a91f0829e Mon Sep 17 00:00:00 2001 From: Jeff Wallace Date: Wed, 4 Dec 2013 11:41:49 -0500 Subject: [PATCH] Performance improvement for artifact sorting. --- .../autopsy/report/ReportGenerator.java | 64 ++++++++++++++----- 1 file changed, 48 insertions(+), 16 deletions(-) diff --git a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java index e0a8c486fe..f67a4c9dc3 100644 --- a/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java +++ b/Core/src/org/sleuthkit/autopsy/report/ReportGenerator.java @@ -34,7 +34,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.Iterator; @@ -51,6 +50,7 @@ import org.sleuthkit.autopsy.casemodule.Case; import org.sleuthkit.autopsy.coreutils.EscapeUtil; import org.sleuthkit.autopsy.coreutils.Logger; import org.sleuthkit.autopsy.coreutils.MessageNotifyUtil; +import org.sleuthkit.autopsy.coreutils.StopWatch; import org.sleuthkit.autopsy.datamodel.Tags; import org.sleuthkit.autopsy.report.ReportProgressPanel.ReportStatus; import org.sleuthkit.datamodel.AbstractFile; @@ -58,7 +58,6 @@ import org.sleuthkit.datamodel.BlackboardArtifact; import org.sleuthkit.datamodel.BlackboardArtifact.ARTIFACT_TYPE; import org.sleuthkit.datamodel.BlackboardAttribute; import org.sleuthkit.datamodel.BlackboardAttribute.ATTRIBUTE_TYPE; -import org.sleuthkit.datamodel.Content; import org.sleuthkit.datamodel.SleuthkitCase; import org.sleuthkit.datamodel.TskCoreException; @@ -375,6 +374,8 @@ public class ReportGenerator { if (tableModules.isEmpty()) { break; } + + System.out.println("----------- " + type.getDisplayName() + " ------------"); Iterator iter = tableModules.iterator(); while (iter.hasNext()) { TableReportModule module = iter.next(); @@ -383,6 +384,10 @@ public class ReportGenerator { } } + for (TableReportModule module : tableModules) { + tableProgress.get(module).updateStatusLabel("Now processing " + type.getDisplayName() + "..."); + } + // If the type is keyword hit or hashset hit, use the helper if (type.equals(ARTIFACT_TYPE.TSK_KEYWORD_HIT)) { writeKeywordHits(tableModules, comment.toString(), tagNamesFilter); @@ -392,7 +397,12 @@ public class ReportGenerator { continue; } + StopWatch stopwatch = new StopWatch(); + stopwatch.start(); List unsortedArtifacts = getFilteredArtifacts(type, tagNamesFilter); + stopwatch.stop(); + System.out.println("Number of Artifacts:\t" + unsortedArtifacts.size()); + System.out.println("getFilteredArtifacts:\t" + stopwatch.getElapsedTime()); if (unsortedArtifacts.isEmpty()) { // Don't report on this artifact type if there are no results @@ -401,7 +411,11 @@ public class ReportGenerator { // The most efficient way to sort all the Artifacts is to add them to a List, and then // sort that List based off a Comparator. Adding to a TreeMap/Set/List sorts the list // each time an element is added, which adds unnecessary overhead if we only need it sorted once. + stopwatch.reset(); + stopwatch.start(); Collections.sort(unsortedArtifacts); + stopwatch.stop(); + System.out.println("Collections.sort:\t" + stopwatch.getElapsedTime()); // Get the column headers appropriate for the artifact type. /* @@@ BC: Seems like a better design here woudl be to have a method that @@ -416,8 +430,7 @@ public class ReportGenerator { continue; } - for (TableReportModule module : tableModules) { - tableProgress.get(module).updateStatusLabel("Now processing " + type.getDisplayName() + "..."); + for (TableReportModule module : tableModules) { // This is a temporary workaround to avoid modifying the TableReportModule interface. if (module instanceof ReportHTML) { @@ -988,7 +1001,12 @@ public class ReportGenerator { * @throws TskCoreException */ private List getArtifactRow(ArtifactData artifactData, TableReportModule module) throws TskCoreException { - Map attributes = getMappedAttributes(artifactData.getAttributes(), module); + Map attributes; + if (module != null) { + attributes = getMappedAttributes(artifactData.getAttributes(), module); + } else { + attributes = artifactData.getMappedAttributes(); + } BlackboardArtifact.ARTIFACT_TYPE type = BlackboardArtifact.ARTIFACT_TYPE.fromID(artifactData.getArtifact().getArtifactTypeID()); @@ -1282,6 +1300,7 @@ public class ReportGenerator { private BlackboardArtifact artifact; private List attributes; private HashSet tags; + private Map mappedAttributes; ArtifactData(BlackboardArtifact artifact, List attrs, HashSet tags) { this.artifact = artifact; @@ -1299,7 +1318,7 @@ public class ReportGenerator { public long getObjectID() { return artifact.getObjectID(); } - @Override + /** * Compares ArtifactData objects by the first attribute they have in * common in their List. @@ -1308,22 +1327,35 @@ public class ReportGenerator { * compared by their artifact id. Should only be used with attributes * of the same type. */ + @Override public int compareTo(ArtifactData data) { - // Get all the attributes for each artifact - int size = ATTRIBUTE_TYPE.values().length; - Map att1 = getMappedAttributes(this.attributes); - Map att2 = getMappedAttributes(data.getAttributes()); - // Compare the attributes one-by-one looking for differences - for(int i=0; i < size; i++) { - String a1 = att1.get(i); - String a2 = att2.get(i); - if((!a1.equals("") && !a2.equals("")) && a1.compareTo(a2) != 0) { - return a1.compareTo(a2); + List thisRow = getRow(); + List dataRow = data.getRow(); + for (int i = 0; i < thisRow.size(); i++) { + int compare = thisRow.get(i).compareTo(dataRow.get(i)); + if (compare != 0) { + return compare; } } // If all attributes are the same, they're most likely duplicates so sort by artifact ID return ((Long)this.getArtifactID()).compareTo((Long)data.getArtifactID()); } + + public Map getMappedAttributes() { + if (mappedAttributes == null) { + mappedAttributes = ReportGenerator.this.getMappedAttributes(attributes); + } + return mappedAttributes; + } + + public List getRow() { + try { + return ReportGenerator.this.getArtifactRow(this, null); + } catch (TskCoreException ex) { + logger.log(Level.WARNING, "Core exception while generating row data for artifact report."); + return Collections.emptyList(); + } + } } }