commit 58fe9880434dc73c74779236ef1f3fcddeec933f
Author: Karsten Loesing <karsten.loesing(a)gmx.net>
Date: Wed May 18 09:49:50 2016 +0200
Add benchmark code.
Implements #19051.
---
CHANGELOG.md | 1 +
build.xml | 13 +-
.../descriptor/benchmark/MeasurePerformance.java | 278 +++++++++++++++++++++
3 files changed, 291 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bfd4755..f694f84 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@
which would mean that only method 1 is supported.
- Stop reporting "-----END .*-----" lines in directory key
certificates as unrecognized.
+ - Add code used for benchmarking.
# Changes in version 1.1.0 - 2015-12-28
diff --git a/build.xml b/build.xml
index 129c4ed..f77f83b 100644
--- a/build.xml
+++ b/build.xml
@@ -68,7 +68,7 @@
</javadoc>
</target>
- <target name="test" depends="compile">
+ <target name="testcompile" depends="init">
<javac destdir="${classes}"
srcdir="${tests}"
source="${source-and-target-java-version}"
@@ -80,6 +80,9 @@
includeantruntime="false">
<classpath refid="classpath"/>
</javac>
+ </target>
+
+ <target name="test" depends="compile,testcompile">
<junit fork="true" haltonfailure="true" printsummary="off">
<classpath refid="classpath"/>
<formatter type="plain" usefile="false"/>
@@ -90,6 +93,14 @@
</junit>
</target>
+ <target name="benchmark" depends="compile,testcompile">
+ <java fork="true"
+ maxmemory="2048m"
+ classname="org.torproject.descriptor.benchmark.MeasurePerformance">
+ <classpath refid="classpath"/>
+ </java>
+ </target>
+
<target name="jar" depends="compile">
<exec executable="git" outputproperty="git.revision">
<arg value="rev-parse" />
diff --git a/test/org/torproject/descriptor/benchmark/MeasurePerformance.java b/test/org/torproject/descriptor/benchmark/MeasurePerformance.java
new file mode 100644
index 0000000..a52020a
--- /dev/null
+++ b/test/org/torproject/descriptor/benchmark/MeasurePerformance.java
@@ -0,0 +1,278 @@
+/* Copyright 2016 The Tor Project
+ * See LICENSE for licensing information */
+package org.torproject.descriptor.benchmark;
+
+import org.torproject.descriptor.Descriptor;
+import org.torproject.descriptor.DescriptorFile;
+import org.torproject.descriptor.DescriptorReader;
+import org.torproject.descriptor.DescriptorSourceFactory;
+import org.torproject.descriptor.ExtraInfoDescriptor;
+import org.torproject.descriptor.Microdescriptor;
+import org.torproject.descriptor.NetworkStatusEntry;
+import org.torproject.descriptor.RelayNetworkStatusConsensus;
+import org.torproject.descriptor.ServerDescriptor;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.SortedMap;
+
+public class MeasurePerformance {
+
+ /* Check if all necessary files are available and then measure
+ * performance of some more or less common use cases. */
+ public static void main(String[] args) {
+ if (!filesAvailable()) {
+ return;
+ }
+ measureAverageAdvertisedBandwidth(new File(resDir, resPaths[0]));
+ pause();
+ measureAverageAdvertisedBandwidth(new File(resDir, resPaths[1]));
+ pause();
+ measureAverageAdvertisedBandwidth(new File(resDir, resPaths[2]));
+ pause();
+ measureCountriesV3Requests(new File(resDir, resPaths[3]));
+ pause();
+ measureCountriesV3Requests(new File(resDir, resPaths[4]));
+ pause();
+ measureAverageRelaysExit(new File(resDir, resPaths[5]));
+ pause();
+ measureAverageRelaysExit(new File(resDir, resPaths[6]));
+ pause();
+ measureAverageRelaysExit(new File(resDir, resPaths[7]));
+ measureFractionRelaysExit80Microdescriptors(
+ new File(resDir, resPaths[8]));
+ measureFractionRelaysExit80Microdescriptors(
+ new File(resDir, resPaths[9]));
+ }
+
+ private static File resDir = new File("res");
+ private static String[] resPaths = new String[] {
+ "archive/relay-descriptors/server-descriptors/"
+ + "server-descriptors-2015-11.tar.xz",
+ "archive/relay-descriptors/server-descriptors/"
+ + "server-descriptors-2015-11.tar",
+ "archive/relay-descriptors/server-descriptors/"
+ + "server-descriptors-2015-11",
+ "archive/relay-descriptors/extra-infos/extra-infos-2015-11.tar.xz",
+ "archive/relay-descriptors/extra-infos/extra-infos-2015-11.tar",
+ "archive/relay-descriptors/consensuses/consensuses-2015-11.tar.xz",
+ "archive/relay-descriptors/consensuses/consensuses-2015-11.tar",
+ "archive/relay-descriptors/consensuses/consensuses-2015-11",
+ "archive/relay-descriptors/microdescs/microdescs-2015-11.tar.xz",
+ "archive/relay-descriptors/microdescs/microdescs-2015-11.tar"
+ };
+
+ private static boolean filesAvailable() {
+ if (!resDir.exists() || !resDir.isDirectory()) {
+ return false;
+ }
+ for (String resPath : resPaths) {
+ if (!(new File(resDir, resPath).exists())) {
+ System.err.println("Missing resource: " + resDir + "/" + resPath);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private static void pause() {
+ try {
+ Thread.sleep(15L * 1000L);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private static void measureAverageAdvertisedBandwidth(
+ File tarballFileOrDirectory) {
+ System.out.println("Starting measureAverageAdvertisedBandwidth");
+ long startedMillis = System.currentTimeMillis();
+ long sumAdvertisedBandwidth = 0, countedServerDescriptors = 0;
+ DescriptorReader descriptorReader =
+ DescriptorSourceFactory.createDescriptorReader();
+ descriptorReader.addTarball(tarballFileOrDirectory);
+ descriptorReader.addDirectory(tarballFileOrDirectory);
+ Iterator<DescriptorFile> descriptorFiles =
+ descriptorReader.readDescriptors();
+ while (descriptorFiles.hasNext()) {
+ DescriptorFile descriptorFile = descriptorFiles.next();
+ for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+ if (!(descriptor instanceof ServerDescriptor)) {
+ continue;
+ }
+ ServerDescriptor serverDescriptor = (ServerDescriptor) descriptor;
+ sumAdvertisedBandwidth += (long) Math.min(Math.min(
+ serverDescriptor.getBandwidthRate(),
+ serverDescriptor.getBandwidthBurst()),
+ serverDescriptor.getBandwidthObserved());
+ countedServerDescriptors++;
+ }
+ }
+ long endedMillis = System.currentTimeMillis();
+ System.out.println("Ending measureAverageAdvertisedBandwidth");
+ System.out.printf("Total time: %d millis%n",
+ endedMillis - startedMillis);
+ System.out.printf("Processed server descriptors: %d%n",
+ countedServerDescriptors);
+ System.out.printf("Average advertised bandwidth: %d%n",
+ sumAdvertisedBandwidth / countedServerDescriptors);
+ System.out.printf("Time per server descriptor: %.6f millis%n",
+ ((double) (endedMillis - startedMillis))
+ / ((double) countedServerDescriptors));
+ }
+
+ private static void measureCountriesV3Requests(File tarballFile) {
+ System.out.println("Starting measureCountriesV3Requests");
+ long startedMillis = System.currentTimeMillis();
+ Set<String> countries = new HashSet<>();
+ long countedExtraInfoDescriptors = 0;
+ DescriptorReader descriptorReader =
+ DescriptorSourceFactory.createDescriptorReader();
+ descriptorReader.addTarball(tarballFile);
+ Iterator<DescriptorFile> descriptorFiles =
+ descriptorReader.readDescriptors();
+ while (descriptorFiles.hasNext()) {
+ DescriptorFile descriptorFile = descriptorFiles.next();
+ for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+ if (!(descriptor instanceof ExtraInfoDescriptor)) {
+ continue;
+ }
+ ExtraInfoDescriptor extraInfoDescriptor =
+ (ExtraInfoDescriptor) descriptor;
+ SortedMap<String, Integer> dirreqV3Reqs =
+ extraInfoDescriptor.getDirreqV3Reqs();
+ if (dirreqV3Reqs != null) {
+ countries.addAll(dirreqV3Reqs.keySet());
+ }
+ countedExtraInfoDescriptors++;
+ }
+ }
+ long endedMillis = System.currentTimeMillis();
+ System.out.println("Ending measureCountriesV3Requests");
+ System.out.printf("Total time: %d millis%n",
+ endedMillis - startedMillis);
+ System.out.printf("Processed extra-info descriptors: %d%n",
+ countedExtraInfoDescriptors);
+ System.out.printf("Number of countries: %d%n",
+ countries.size());
+ System.out.printf("Time per extra-info descriptor: %.6f millis%n",
+ ((double) (endedMillis - startedMillis))
+ / ((double) countedExtraInfoDescriptors));
+ }
+
+ private static void measureAverageRelaysExit(
+ File tarballFileOrDirectory) {
+ System.out.println("Starting measureAverageRelaysExit");
+ long startedMillis = System.currentTimeMillis();
+ long totalRelaysWithExitFlag = 0L, totalRelays = 0L,
+ countedConsensuses = 0L;
+ DescriptorReader descriptorReader =
+ DescriptorSourceFactory.createDescriptorReader();
+ descriptorReader.addTarball(tarballFileOrDirectory);
+ descriptorReader.addDirectory(tarballFileOrDirectory);
+ Iterator<DescriptorFile> descriptorFiles =
+ descriptorReader.readDescriptors();
+ while (descriptorFiles.hasNext()) {
+ DescriptorFile descriptorFile = descriptorFiles.next();
+ for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+ if (!(descriptor instanceof RelayNetworkStatusConsensus)) {
+ continue;
+ }
+ RelayNetworkStatusConsensus consensus =
+ (RelayNetworkStatusConsensus) descriptor;
+ for (NetworkStatusEntry entry :
+ consensus.getStatusEntries().values()) {
+ if (entry.getFlags().contains("Exit")) {
+ totalRelaysWithExitFlag++;
+ }
+ totalRelays++;
+ }
+ countedConsensuses++;
+ }
+ }
+ long endedMillis = System.currentTimeMillis();
+ System.out.println("Ending measureAverageRelaysExit");
+ System.out.printf("Total time: %d millis%n",
+ endedMillis - startedMillis);
+ System.out.printf("Processed consensuses: %d%n", countedConsensuses);
+ System.out.printf("Total number of status entries: %d%n",
+ totalRelays);
+ System.out.printf("Total number of status entries with Exit flag: "
+ + "%d%n", totalRelaysWithExitFlag);
+ System.out.printf("Average number of relays with Exit Flag: %.2f%n",
+ (double) totalRelaysWithExitFlag / (double) totalRelays);
+ System.out.printf("Time per consensus: %.6f millis%n",
+ ((double) (endedMillis - startedMillis))
+ / ((double) countedConsensuses));
+ }
+
+ private static void measureFractionRelaysExit80Microdescriptors(
+ File tarballFile) {
+ System.out.println("Starting "
+ + "measureFractionRelaysExit80Microdescriptors");
+ long startedMillis = System.currentTimeMillis();
+ long totalRelaysWithExitFlag = 0L, countedMicrodescriptors = 0L;
+ DescriptorReader descriptorReader =
+ DescriptorSourceFactory.createDescriptorReader();
+ descriptorReader.addTarball(tarballFile);
+ Iterator<DescriptorFile> descriptorFiles =
+ descriptorReader.readDescriptors();
+ while (descriptorFiles.hasNext()) {
+ DescriptorFile descriptorFile = descriptorFiles.next();
+ for (Descriptor descriptor : descriptorFile.getDescriptors()) {
+ if (!(descriptor instanceof Microdescriptor)) {
+ continue;
+ }
+ countedMicrodescriptors++;
+ Microdescriptor microdescriptor =
+ (Microdescriptor) descriptor;
+ String defaultPolicy = microdescriptor.getDefaultPolicy();
+ if (defaultPolicy == null) {
+ continue;
+ }
+ boolean accept = "accept".equals(
+ microdescriptor.getDefaultPolicy());
+ for (String ports : microdescriptor.getPortList().split(",")) {
+ if (ports.contains("-")) {
+ String[] parts = ports.split("-");
+ int from = Integer.parseInt(parts[0]);
+ int to = Integer.parseInt(parts[1]);
+ if (from <= 80 && to >= 80) {
+ if (accept) {
+ totalRelaysWithExitFlag++;
+ }
+ } else if (to > 80) {
+ if (!accept) {
+ totalRelaysWithExitFlag++;
+ }
+ break;
+ }
+ } else if ("80".equals(ports)) {
+ if (accept) {
+ totalRelaysWithExitFlag++;
+ }
+ break;
+ }
+ }
+ }
+ }
+ long endedMillis = System.currentTimeMillis();
+ System.out.println("Ending "
+ + "measureFractionRelaysExit80Microdescriptors");
+ System.out.printf("Total time: %d millis%n",
+ endedMillis - startedMillis);
+ System.out.printf("Processed microdescriptors: %d%n",
+ countedMicrodescriptors);
+ System.out.printf("Total number of microdescriptors that exit to 80: "
+ + "%d%n", totalRelaysWithExitFlag);
+ System.out.printf("Average number of relays that exit to 80: %.2f%n",
+ (double) totalRelaysWithExitFlag
+ / (double) countedMicrodescriptors);
+ System.out.printf("Time per microdescriptor: %.6f millis%n",
+ ((double) (endedMillis - startedMillis))
+ / ((double) countedMicrodescriptors));
+ }
+}
+