[tor-commits] [metrics-lib/master] Avoid parsing descriptor contents to Lists or Sets.

karsten at torproject.org karsten at torproject.org
Wed Jun 18 15:07:27 UTC 2014


commit c439d346b9201032c118e0cadf2e4230bb9d7dca
Author: Karsten Loesing <karsten.loesing at gmx.net>
Date:   Tue Jun 17 20:26:47 2014 +0200

    Avoid parsing descriptor contents to Lists or Sets.
    
    If we can easily determine the number of List or Set elements, we can as
    well store their contents in arrays and convert those to List or Set
    instances when requested.  This can save us some memory and doesn't cost
    much performance.
---
 .../descriptor/impl/ExtraInfoDescriptorImpl.java   |   30 +++----
 .../descriptor/impl/MicrodescriptorImpl.java       |   19 +++--
 .../descriptor/impl/NetworkStatusImpl.java         |   20 +++++
 .../torproject/descriptor/impl/ParseHelper.java    |   28 +++----
 .../impl/RelayNetworkStatusConsensusImpl.java      |   38 +++------
 .../descriptor/impl/RelayNetworkStatusImpl.java    |   38 +++------
 .../impl/RelayNetworkStatusVoteImpl.java           |   47 ++++-------
 .../descriptor/impl/ServerDescriptorImpl.java      |   82 ++++++++++----------
 .../descriptor/impl/TorperfResultImpl.java         |   55 +++++++------
 9 files changed, 163 insertions(+), 194 deletions(-)

diff --git a/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
index 68cb850..13fdfa8 100644
--- a/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/ExtraInfoDescriptorImpl.java
@@ -425,7 +425,7 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl
       String[] partsNoOpt) throws DescriptorParseException {
     this.cellProcessedCells = ParseHelper.
         parseCommaSeparatedIntegerValueList(line, partsNoOpt, 1);
-    if (this.cellProcessedCells.size() != 10) {
+    if (this.cellProcessedCells.length != 10) {
       throw new DescriptorParseException("There must be exact ten values "
           + "in line '" + line + "'.");
     }
@@ -435,7 +435,7 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl
       String[] partsNoOpt) throws DescriptorParseException {
     this.cellQueuedCells = ParseHelper.parseCommaSeparatedDoubleValueList(
         line, partsNoOpt, 1);
-    if (this.cellQueuedCells.size() != 10) {
+    if (this.cellQueuedCells.length != 10) {
       throw new DescriptorParseException("There must be exact ten values "
           + "in line '" + line + "'.");
     }
@@ -445,7 +445,7 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl
       String[] partsNoOpt) throws DescriptorParseException {
     this.cellTimeInQueue = ParseHelper.
         parseCommaSeparatedIntegerValueList(line, partsNoOpt, 1);
-    if (this.cellTimeInQueue.size() != 10) {
+    if (this.cellTimeInQueue.length != 10) {
       throw new DescriptorParseException("There must be exact ten values "
           + "in line '" + line + "'.");
     }
@@ -474,16 +474,16 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl
         6);
     this.connBiDirectStatsEndMillis = parsedStatsEndData[0];
     this.connBiDirectStatsIntervalLength = parsedStatsEndData[1];
-    List<Integer> parsedConnBiDirectStats = ParseHelper.
+    Integer[] parsedConnBiDirectStats = ParseHelper.
         parseCommaSeparatedIntegerValueList(line, partsNoOpt, 5);
-    if (parsedConnBiDirectStats.size() != 4) {
+    if (parsedConnBiDirectStats.length != 4) {
       throw new DescriptorParseException("Illegal line '" + line + "' in "
           + "extra-info descriptor.");
     }
-    this.connBiDirectBelow = parsedConnBiDirectStats.get(0);
-    this.connBiDirectRead = parsedConnBiDirectStats.get(1);
-    this.connBiDirectWrite = parsedConnBiDirectStats.get(2);
-    this.connBiDirectBoth = parsedConnBiDirectStats.get(3);
+    this.connBiDirectBelow = parsedConnBiDirectStats[0];
+    this.connBiDirectRead = parsedConnBiDirectStats[1];
+    this.connBiDirectWrite = parsedConnBiDirectStats[2];
+    this.connBiDirectBoth = parsedConnBiDirectStats[3];
   }
 
   private void parseExitStatsEndLine(String line, String lineNoOpt,
@@ -818,22 +818,22 @@ public class ExtraInfoDescriptorImpl extends DescriptorImpl
     return this.cellStatsIntervalLength;
   }
 
-  private List<Integer> cellProcessedCells;
+  private Integer[] cellProcessedCells;
   public List<Integer> getCellProcessedCells() {
     return this.cellProcessedCells == null ? null :
-        new ArrayList<Integer>(this.cellProcessedCells);
+        Arrays.asList(this.cellProcessedCells);
   }
 
-  private List<Double> cellQueuedCells;
+  private Double[] cellQueuedCells;
   public List<Double> getCellQueuedCells() {
     return this.cellQueuedCells == null ? null :
-        new ArrayList<Double>(this.cellQueuedCells);
+        Arrays.asList(this.cellQueuedCells);
   }
 
-  private List<Integer> cellTimeInQueue;
+  private Integer[] cellTimeInQueue;
   public List<Integer> getCellTimeInQueue() {
     return this.cellTimeInQueue == null ? null :
-        new ArrayList<Integer>(this.cellTimeInQueue);
+        Arrays.asList(this.cellTimeInQueue);
   }
 
   private int cellCircuitsPerDecile = -1;
diff --git a/src/org/torproject/descriptor/impl/MicrodescriptorImpl.java b/src/org/torproject/descriptor/impl/MicrodescriptorImpl.java
index c27e946..12cbdd5 100644
--- a/src/org/torproject/descriptor/impl/MicrodescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/MicrodescriptorImpl.java
@@ -135,7 +135,7 @@ public class MicrodescriptorImpl extends DescriptorImpl
 
   private void parseFamilyLine(String line, String[] parts)
       throws DescriptorParseException {
-    this.familyEntries = new ArrayList<String>();
+    String[] familyEntries = new String[parts.length - 1];
     for (int i = 1; i < parts.length; i++) {
       if (parts[i].startsWith("$")) {
         if (parts[i].contains("=") ^ parts[i].contains("~")) {
@@ -143,19 +143,18 @@ public class MicrodescriptorImpl extends DescriptorImpl
           String fingerprint = ParseHelper.parseTwentyByteHexString(line,
               parts[i].substring(1, parts[i].indexOf(separator)));
           String nickname = ParseHelper.parseNickname(line,
-              parts[i].substring(parts[i].indexOf(
-              separator) + 1));
-          this.familyEntries.add("$" + fingerprint + separator
-              + nickname);
+              parts[i].substring(parts[i].indexOf(separator) + 1));
+          familyEntries[i - 1] = "$" + fingerprint + separator + nickname;
         } else {
-          this.familyEntries.add("$"
+          familyEntries[i - 1] = "$"
               + ParseHelper.parseTwentyByteHexString(line,
-              parts[i].substring(1)));
+              parts[i].substring(1));
         }
       } else {
-        this.familyEntries.add(ParseHelper.parseNickname(line, parts[i]));
+        familyEntries[i - 1] = ParseHelper.parseNickname(line, parts[i]);
       }
     }
+    this.familyEntries = familyEntries;
   }
 
   private void parsePLine(String line, String[] parts)
@@ -234,10 +233,10 @@ public class MicrodescriptorImpl extends DescriptorImpl
     return new ArrayList<String>(this.orAddresses);
   }
 
-  private List<String> familyEntries;
+  private String[] familyEntries;
   public List<String> getFamilyEntries() {
     return this.familyEntries == null ? null :
-        new ArrayList<String>(this.familyEntries);
+        Arrays.asList(this.familyEntries);
   }
   private String defaultPolicy;
   public String getDefaultPolicy() {
diff --git a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
index 6358ca3..d57128e 100644
--- a/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/NetworkStatusImpl.java
@@ -173,6 +173,26 @@ public abstract class NetworkStatusImpl extends DescriptorImpl {
     }
   }
 
+  protected String[] parseClientOrServerVersions(String line,
+      String[] parts) throws DescriptorParseException {
+    String[] result = null;
+    if (parts.length > 2) {
+      throw new DescriptorParseException("Illegal versions line '" + line
+          + "'.");
+    } else if (parts.length == 2) {
+      result = parts[1].split(",", -1);
+      for (String version : result) {
+        if (version.length() < 1) {
+          throw new DescriptorParseException("Illegal versions line '"
+              + line + "'.");
+        }
+      }
+    } else if (parts.length == 1) {
+      result = new String[0];
+    }
+    return result;
+  }
+
   protected void parseStatusEntry(byte[] statusEntryBytes)
       throws DescriptorParseException {
     NetworkStatusEntryImpl statusEntry = new NetworkStatusEntryImpl(
diff --git a/src/org/torproject/descriptor/impl/ParseHelper.java b/src/org/torproject/descriptor/impl/ParseHelper.java
index 8b314fd..4fbe34a 100644
--- a/src/org/torproject/descriptor/impl/ParseHelper.java
+++ b/src/org/torproject/descriptor/impl/ParseHelper.java
@@ -5,9 +5,7 @@ package org.torproject.descriptor.impl;
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import java.util.SortedMap;
 import java.util.TimeZone;
@@ -364,54 +362,56 @@ public class ParseHelper {
     return result;
   }
 
-  public static List<Integer> parseCommaSeparatedIntegerValueList(
+  public static Integer[] parseCommaSeparatedIntegerValueList(
       String line, String[] partsNoOpt, int index)
       throws DescriptorParseException {
-    List<Integer> result = new ArrayList<Integer>();
+    Integer[] result = null;
     if (partsNoOpt.length < index) {
       throw new DescriptorParseException("Line '" + line + "' does not "
           + "contain a comma-separated value list at index " + index
           + ".");
-    } else if (partsNoOpt.length > index + 1 ) {
+    } else if (partsNoOpt.length > index + 1) {
       throw new DescriptorParseException("Line '" + line + "' contains "
           + "unrecognized values beyond the expected comma-separated "
           + "value list at index " + index + ".");
     } else if (partsNoOpt.length > index) {
       String[] listElements = partsNoOpt[index].split(",", -1);
-      for (String listElement : listElements) {
+      result = new Integer[listElements.length];
+      for (int i = 0; i < listElements.length; i++) {
         try {
-          result.add(Integer.parseInt(listElement));
+          result[i] = Integer.parseInt(listElements[i]);
         } catch (NumberFormatException e) {
           throw new DescriptorParseException("Line '" + line + "' "
               + "contains an illegal value in list element '"
-              + listElement + "'.");
+              + listElements[i] + "'.");
         }
       }
     }
     return result;
   }
 
-  public static List<Double> parseCommaSeparatedDoubleValueList(
+  public static Double[] parseCommaSeparatedDoubleValueList(
       String line, String[] partsNoOpt, int index)
       throws DescriptorParseException {
-    List<Double> result = new ArrayList<Double>();
+    Double[] result = null;
     if (partsNoOpt.length < index) {
       throw new DescriptorParseException("Line '" + line + "' does not "
           + "contain a comma-separated value list at index " + index
           + ".");
-    } else if (partsNoOpt.length > index + 1 ) {
+    } else if (partsNoOpt.length > index + 1) {
       throw new DescriptorParseException("Line '" + line + "' contains "
           + "unrecognized values beyond the expected comma-separated "
           + "value list at index " + index + ".");
     } else if (partsNoOpt.length > index) {
       String[] listElements = partsNoOpt[index].split(",", -1);
-      for (String listElement : listElements) {
+      result = new Double[listElements.length];
+      for (int i = 0; i < listElements.length; i++) {
         try {
-          result.add(Double.parseDouble(listElement));
+          result[i] = Double.parseDouble(listElements[i]);
         } catch (NumberFormatException e) {
           throw new DescriptorParseException("Line '" + line + "' "
               + "contains an illegal value in list element '"
-              + listElement + "'.");
+              + listElements[i] + "'.");
         }
       }
     }
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
index faad733..3eb69b5 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusConsensusImpl.java
@@ -249,37 +249,17 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
         line, parts);
   }
 
-  private List<String> parseClientOrServerVersions(String line,
-      String[] parts) throws DescriptorParseException {
-    List<String> result = new ArrayList<String>();
-    if (parts.length == 1) {
-      return result;
-    } else if (parts.length > 2) {
-      throw new DescriptorParseException("Illegal versions line '" + line
-          + "'.");
-    }
-    String[] versions = parts[1].split(",", -1);
-    for (int i = 0; i < versions.length; i++) {
-      String version = versions[i];
-      if (version.length() < 1) {
-        throw new DescriptorParseException("Illegal versions line '"
-            + line + "'.");
-      }
-      result.add(version);
-    }
-    return result;
-  }
-
   private void parseKnownFlagsLine(String line, String[] parts)
       throws DescriptorParseException {
     if (parts.length < 2) {
       throw new DescriptorParseException("No known flags in line '" + line
           + "'.");
     }
-    this.knownFlags = new TreeSet<String>();
+    String[] knownFlags = new String[parts.length - 1];
     for (int i = 1; i < parts.length; i++) {
-      this.knownFlags.add(parts[i]);
+      knownFlags[i - 1] = parts[i];
     }
+    this.knownFlags = knownFlags;
   }
 
   private void parseParamsLine(String line, String[] parts)
@@ -339,21 +319,21 @@ public class RelayNetworkStatusConsensusImpl extends NetworkStatusImpl
     return this.distSeconds;
   }
 
-  private List<String> recommendedClientVersions;
+  private String[] recommendedClientVersions;
   public List<String> getRecommendedClientVersions() {
     return this.recommendedClientVersions == null ? null :
-        new ArrayList<String>(this.recommendedClientVersions);
+        Arrays.asList(this.recommendedClientVersions);
   }
 
-  private List<String> recommendedServerVersions;
+  private String[] recommendedServerVersions;
   public List<String> getRecommendedServerVersions() {
     return this.recommendedServerVersions == null ? null :
-        new ArrayList<String>(this.recommendedServerVersions);
+        Arrays.asList(this.recommendedServerVersions);
   }
 
-  private SortedSet<String> knownFlags;
+  private String[] knownFlags;
   public SortedSet<String> getKnownFlags() {
-    return new TreeSet<String>(this.knownFlags);
+    return new TreeSet<String>(Arrays.asList(this.knownFlags));
   }
 
   private SortedMap<String, Integer> consensusParams;
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
index 8f0d984..ab86327 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusImpl.java
@@ -246,27 +246,6 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
         line, parts);
   }
 
-  private List<String> parseClientOrServerVersions(String line,
-      String[] parts) throws DescriptorParseException {
-    List<String> result = new ArrayList<String>();
-    if (parts.length == 1) {
-      return result;
-    } else if (parts.length > 2) {
-      throw new DescriptorParseException("Illegal versions line '" + line
-          + "'.");
-    }
-    String[] versions = parts[1].split(",", -1);
-    for (int i = 0; i < versions.length; i++) {
-      String version = versions[i];
-      if (version.length() < 1) {
-        throw new DescriptorParseException("Illegal versions line '"
-            + line + "'.");
-      }
-      result.add(version);
-    }
-    return result;
-  }
-
   private void parsePublishedLine(String line, String[] parts)
       throws DescriptorParseException {
     this.publishedMillis = ParseHelper.parseTimestampAtIndex(line, parts,
@@ -275,10 +254,11 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
 
   private void parseDirOptionsLine(String line, String[] parts)
       throws DescriptorParseException {
-    this.dirOptions = new TreeSet<String>();
+    String[] dirOptions = new String[parts.length - 1];
     for (int i = 1; i < parts.length; i++) {
-      this.dirOptions.add(parts[i]);
+      dirOptions[i - 1] = parts[i];
     }
+    this.dirOptions = dirOptions;
   }
 
   private void parseDirectorySignatureLine(String line, String[] parts)
@@ -329,16 +309,16 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
     return this.dirSigningKey;
   }
 
-  private List<String> recommendedClientVersions;
+  private String[] recommendedClientVersions;
   public List<String> getRecommendedClientVersions() {
     return this.recommendedClientVersions == null ? null :
-        new ArrayList<String>(this.recommendedClientVersions);
+        Arrays.asList(this.recommendedClientVersions);
   }
 
-  private List<String> recommendedServerVersions;
+  private String[] recommendedServerVersions;
   public List<String> getRecommendedServerVersions() {
     return this.recommendedServerVersions == null ? null :
-        new ArrayList<String>(this.recommendedServerVersions);
+        Arrays.asList(this.recommendedServerVersions);
   }
 
   private long publishedMillis;
@@ -346,9 +326,9 @@ public class RelayNetworkStatusImpl extends NetworkStatusImpl
     return this.publishedMillis;
   }
 
-  private SortedSet<String> dirOptions;
+  private String[] dirOptions;
   public SortedSet<String> getDirOptions() {
-    return new TreeSet<String>(this.dirOptions);
+    return new TreeSet<String>(Arrays.asList(this.dirOptions));
   }
 
   private String nickname;
diff --git a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
index 9dbc1f0..c5c867e 100644
--- a/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
+++ b/src/org/torproject/descriptor/impl/RelayNetworkStatusVoteImpl.java
@@ -165,7 +165,7 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
       throw new DescriptorParseException("Illegal line '" + line
           + "' in vote.");
     }
-    this.consensusMethods = new ArrayList<Integer>();
+    Integer[] consensusMethods = new Integer[parts.length - 1];
     for (int i = 1; i < parts.length; i++) {
       int consensusMethod = -1;
       try {
@@ -177,8 +177,9 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
         throw new DescriptorParseException("Illegal consensus method "
             + "number in line '" + line + "'.");
       }
-      this.consensusMethods.add(Integer.parseInt(parts[i]));
+      consensusMethods[i - 1] = consensusMethod;
     }
+    this.consensusMethods = consensusMethods;
   }
 
   private void parsePublishedLine(String line, String[] parts)
@@ -232,37 +233,17 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
         line, parts);
   }
 
-  private List<String> parseClientOrServerVersions(String line,
-      String[] parts) throws DescriptorParseException {
-    List<String> result = new ArrayList<String>();
-    if (parts.length == 1) {
-      return result;
-    } else if (parts.length > 2) {
-      throw new DescriptorParseException("Illegal versions line '" + line
-          + "'.");
-    }
-    String[] versions = parts[1].split(",", -1);
-    for (int i = 0; i < versions.length; i++) {
-      String version = versions[i];
-      if (version.length() < 1) {
-        throw new DescriptorParseException("Illegal versions line '"
-            + line + "'.");
-      }
-      result.add(version);
-    }
-    return result;
-  }
-
   private void parseKnownFlagsLine(String line, String[] parts)
       throws DescriptorParseException {
     if (parts.length < 2) {
       throw new DescriptorParseException("No known flags in line '" + line
           + "'.");
     }
-    this.knownFlags = new TreeSet<String>();
+    String[] knownFlags = new String[parts.length - 1];
     for (int i = 1; i < parts.length; i++) {
-      this.knownFlags.add(parts[i]);
+      knownFlags[i - 1] = parts[i];
     }
+    this.knownFlags = knownFlags;
   }
 
   private void parseFlagThresholdsLine(String line, String[] parts)
@@ -468,9 +449,9 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
     return this.networkStatusVersion;
   }
 
-  private List<Integer> consensusMethods;
+  private Integer[] consensusMethods;
   public List<Integer> getConsensusMethods() {
-    return new ArrayList<Integer>(this.consensusMethods);
+    return Arrays.asList(this.consensusMethods);
   }
 
   private long publishedMillis;
@@ -503,21 +484,21 @@ public class RelayNetworkStatusVoteImpl extends NetworkStatusImpl
     return this.distSeconds;
   }
 
-  private List<String> recommendedClientVersions;
+  private String[] recommendedClientVersions;
   public List<String> getRecommendedClientVersions() {
     return this.recommendedClientVersions == null ? null :
-        new ArrayList<String>(this.recommendedClientVersions);
+        Arrays.asList(this.recommendedClientVersions);
   }
 
-  private List<String> recommendedServerVersions;
+  private String[] recommendedServerVersions;
   public List<String> getRecommendedServerVersions() {
     return this.recommendedServerVersions == null ? null :
-        new ArrayList<String>(this.recommendedServerVersions);
+        Arrays.asList(this.recommendedServerVersions);
   }
 
-  private SortedSet<String> knownFlags;
+  private String[] knownFlags;
   public SortedSet<String> getKnownFlags() {
-    return new TreeSet<String>(this.knownFlags);
+    return new TreeSet<String>(Arrays.asList(this.knownFlags));
   }
 
   private long stableUptime;
diff --git a/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java
index 6adc689..6a59038 100644
--- a/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java
+++ b/src/org/torproject/descriptor/impl/ServerDescriptorImpl.java
@@ -330,7 +330,7 @@ public class ServerDescriptorImpl extends DescriptorImpl
 
   private void parseFamilyLine(String line, String lineNoOpt,
       String[] partsNoOpt) throws DescriptorParseException {
-    this.familyEntries = new ArrayList<String>();
+    String[] familyEntries = new String[partsNoOpt.length - 1];
     for (int i = 1; i < partsNoOpt.length; i++) {
       if (partsNoOpt[i].startsWith("$")) {
         if (partsNoOpt[i].contains("=") ^ partsNoOpt[i].contains("~")) {
@@ -341,18 +341,18 @@ public class ServerDescriptorImpl extends DescriptorImpl
           String nickname = ParseHelper.parseNickname(line,
               partsNoOpt[i].substring(partsNoOpt[i].indexOf(
               separator) + 1));
-          this.familyEntries.add("$" + fingerprint + separator
-              + nickname);
+          familyEntries[i - 1] = "$" + fingerprint + separator + nickname;
         } else {
-          this.familyEntries.add("$"
+          familyEntries[i - 1] = "$"
               + ParseHelper.parseTwentyByteHexString(line,
-              partsNoOpt[i].substring(1)));
+              partsNoOpt[i].substring(1));
         }
       } else {
-        this.familyEntries.add(ParseHelper.parseNickname(line,
-            partsNoOpt[i]));
+        familyEntries[i - 1] = ParseHelper.parseNickname(line,
+            partsNoOpt[i]);
       }
     }
+    this.familyEntries = familyEntries;
   }
 
   private void parseReadHistoryLine(String line, String lineNoOpt,
@@ -400,15 +400,15 @@ public class ServerDescriptorImpl extends DescriptorImpl
 
   private void parseHiddenServiceDirLine(String line, String lineNoOpt,
       String[] partsNoOpt) throws DescriptorParseException {
-    this.hiddenServiceDirVersions = new ArrayList<Integer>();
     if (partsNoOpt.length == 1) {
-      this.hiddenServiceDirVersions.add(2);
+      this.hiddenServiceDirVersions = new Integer[] { 2 };
     } else {
       try {
+        Integer[] result = new Integer[partsNoOpt.length - 1];
         for (int i = 1; i < partsNoOpt.length; i++) {
-          this.hiddenServiceDirVersions.add(Integer.parseInt(
-              partsNoOpt[i]));
+          result[i - 1] = Integer.parseInt(partsNoOpt[i]);
         }
+        this.hiddenServiceDirVersions = result;
       } catch (NumberFormatException e) {
         throw new DescriptorParseException("Illegal value in line '"
             + line + "'.");
@@ -418,32 +418,32 @@ public class ServerDescriptorImpl extends DescriptorImpl
 
   private void parseProtocolsLine(String line, String lineNoOpt,
       String[] partsNoOpt) throws DescriptorParseException {
-    boolean isValid = true;
-    this.linkProtocolVersions = new ArrayList<Integer>();
-    this.circuitProtocolVersions = new ArrayList<Integer>();
-    List<Integer> protocolVersions = null;
+    int linkIndex = -1, circuitIndex = -1;
     for (int i = 1; i < partsNoOpt.length; i++) {
-      String part = partsNoOpt[i];
-      if (part.equals("Link")) {
-        protocolVersions = this.linkProtocolVersions;
-      } else if (part.equals("Circuit")) {
-        protocolVersions = this.circuitProtocolVersions;
-      } else if (protocolVersions == null) {
-        isValid = false;
-        break;
-      } else {
-        try {
-          protocolVersions.add(Integer.parseInt(part));
-        } catch (NumberFormatException e) {
-          isValid = false;
-          break;
-        }
+      if (partsNoOpt[i].equals("Link")) {
+        linkIndex = i;
+      } else if (partsNoOpt[i].equals("Circuit")) {
+        circuitIndex = i;
       }
     }
-    if (protocolVersions != this.circuitProtocolVersions) {
-      isValid = false;
+    if (linkIndex < 0 || circuitIndex < 0 || circuitIndex < linkIndex) {
+      throw new DescriptorParseException("Illegal line '" + line + "'.");
     }
-    if (!isValid) {
+    try {
+      Integer[] linkProtocolVersions =
+          new Integer[circuitIndex - linkIndex - 1];
+      for (int i = linkIndex + 1, j = 0; i < circuitIndex; i++, j++) {
+        linkProtocolVersions[j] = Integer.parseInt(partsNoOpt[i]);
+      }
+      Integer[] circuitProtocolVersions =
+          new Integer[partsNoOpt.length - circuitIndex - 1];
+      for (int i = circuitIndex + 1, j = 0; i < partsNoOpt.length;
+          i++, j++) {
+        circuitProtocolVersions[j] = Integer.parseInt(partsNoOpt[i]);
+      }
+      this.linkProtocolVersions = linkProtocolVersions;
+      this.circuitProtocolVersions = circuitProtocolVersions;
+    } catch (NumberFormatException e) {
       throw new DescriptorParseException("Illegal line '" + line + "'.");
     }
   }
@@ -639,10 +639,10 @@ public class ServerDescriptorImpl extends DescriptorImpl
     return this.contact;
   }
 
-  private List<String> familyEntries;
+  private String[] familyEntries;
   public List<String> getFamilyEntries() {
     return this.familyEntries == null ? null :
-        new ArrayList<String>(this.familyEntries);
+        Arrays.asList(this.familyEntries);
   }
 
   private BandwidthHistory readHistory;
@@ -670,22 +670,22 @@ public class ServerDescriptorImpl extends DescriptorImpl
     return this.extraInfoDigest;
   }
 
-  private List<Integer> hiddenServiceDirVersions;
+  private Integer[] hiddenServiceDirVersions;
   public List<Integer> getHiddenServiceDirVersions() {
     return this.hiddenServiceDirVersions == null ? null :
-        new ArrayList<Integer>(this.hiddenServiceDirVersions);
+        Arrays.asList(this.hiddenServiceDirVersions);
   }
 
-  private List<Integer> linkProtocolVersions;
+  private Integer[] linkProtocolVersions;
   public List<Integer> getLinkProtocolVersions() {
     return this.linkProtocolVersions == null ? null :
-        new ArrayList<Integer>(this.linkProtocolVersions);
+        Arrays.asList(this.linkProtocolVersions);
   }
 
-  private List<Integer> circuitProtocolVersions;
+  private Integer[] circuitProtocolVersions;
   public List<Integer> getCircuitProtocolVersions() {
     return this.circuitProtocolVersions == null ? null :
-        new ArrayList<Integer>(this.circuitProtocolVersions);
+        Arrays.asList(this.circuitProtocolVersions);
   }
 
   private boolean allowSingleHopExits;
diff --git a/src/org/torproject/descriptor/impl/TorperfResultImpl.java b/src/org/torproject/descriptor/impl/TorperfResultImpl.java
index 6a8c1c7..9045498 100644
--- a/src/org/torproject/descriptor/impl/TorperfResultImpl.java
+++ b/src/org/torproject/descriptor/impl/TorperfResultImpl.java
@@ -241,17 +241,14 @@ public class TorperfResultImpl extends DescriptorImpl
       String line) throws DescriptorParseException {
     String percentileString = keyValue.substring("DATAPERC".length(),
         keyValue.indexOf("="));
-    if (!unparsedPercentiles.contains(percentileString)) {
+    if (!this.unparsedPercentiles.contains(percentileString)) {
       throw new DescriptorParseException("Illegal value in '" + keyValue
           + "' in line '" + line + "'.");
     }
-    unparsedPercentiles.remove(percentileString);
-    if (this.dataPercentiles == null) {
-      this.dataPercentiles = new TreeMap<Integer, Long>();
-    }
-    int percentile = Integer.parseInt(percentileString);
+    this.unparsedPercentiles.remove(percentileString);
+    int decileIndex = (Integer.parseInt(percentileString) / 10) - 1;
     long timestamp = this.parseTimestamp(value, keyValue, line);
-    this.dataPercentiles.put(percentile, timestamp);
+    this.dataDeciles[decileIndex] = timestamp;
   }
 
   private void parseLaunch(String value, String keyValue, String line)
@@ -266,24 +263,27 @@ public class TorperfResultImpl extends DescriptorImpl
 
   private void parsePath(String value, String keyValue, String line)
       throws DescriptorParseException {
-    this.path = new ArrayList<String>();
-    for (String fingerprint : value.split(",")) {
-      if (fingerprint.length() != 41) {
+    String[] valueParts = value.split(",");
+    String[] result = new String[valueParts.length];
+    for (int i = 0; i < valueParts.length; i++) {
+      if (valueParts[i].length() != 41) {
         throw new DescriptorParseException("Illegal value in '" + keyValue
             + "' in line '" + line + "'.");
       }
-      this.path.add(ParseHelper.parseTwentyByteHexString(line,
-          fingerprint.substring(1)));
+      result[i] = ParseHelper.parseTwentyByteHexString(line,
+          valueParts[i].substring(1));
     }
+    this.path = result;
   }
 
   private void parseBuildTimes(String value, String keyValue, String line)
       throws DescriptorParseException {
-    this.buildTimes = new ArrayList<Long>();
-    for (String buildTimeString : value.split(",")) {
-      this.buildTimes.add(this.parseTimestamp(buildTimeString, keyValue,
-          line));
+    String[] valueParts = value.split(",");
+    Long[] result = new Long[valueParts.length];
+    for (int i = 0; i < valueParts.length; i++) {
+      result[i] = this.parseTimestamp(valueParts[i], keyValue, line);
     }
+    this.buildTimes = result;
   }
 
   private void parseTimeout(String value, String keyValue, String line)
@@ -417,10 +417,18 @@ public class TorperfResultImpl extends DescriptorImpl
     return this.didTimeout;
   }
 
-  private SortedMap<Integer, Long> dataPercentiles;
+  private Long[] dataDeciles = new Long[9];
   public SortedMap<Integer, Long> getDataPercentiles() {
-    return this.dataPercentiles == null ? null :
-        new TreeMap<Integer, Long>(this.dataPercentiles);
+    if (this.dataDeciles == null) {
+      return null;
+    }
+    SortedMap<Integer, Long> result = new TreeMap<Integer, Long>();
+    for (int i = 0; i < dataDeciles.length; i++) {
+      if (dataDeciles[i] > 0L) {
+        result.put(10 * (i + 1), dataDeciles[i]);
+      }
+    }
+    return result;
   }
 
   private long launchMillis = -1L;
@@ -433,14 +441,15 @@ public class TorperfResultImpl extends DescriptorImpl
     return this.usedAtMillis;
   }
 
-  private List<String> path;
+  private String[] path;
   public List<String> getPath() {
-    return new ArrayList<String>(this.path);
+    return this.path == null ? null : Arrays.asList(this.path);
   }
 
-  private List<Long> buildTimes;
+  private Long[] buildTimes;
   public List<Long> getBuildTimes() {
-    return new ArrayList<Long>(this.buildTimes);
+    return this.buildTimes == null ? null :
+        Arrays.asList(this.buildTimes);
   }
 
   private long timeout = -1L;





More information about the tor-commits mailing list