commit a239d995242dd9205f7826a29ccf793bfc7eb803 Author: David Fifield david@bamsoftware.com Date: Sun Oct 30 03:29:47 2011 -0700
Add throughput measurement script. --- experiments/README | 45 ++++++++++++- experiments/common.sh | 34 ++++++++++ experiments/throughput/throughput-all.sh | 5 ++ experiments/throughput/throughput.sh | 105 ++++++++++++++++++++++++++++++ 4 files changed, 185 insertions(+), 4 deletions(-)
diff --git a/experiments/README b/experiments/README index 5d65b28..ff8b416 100644 --- a/experiments/README +++ b/experiments/README @@ -1,6 +1,43 @@ -Scripts for running experiments. +This directory contains scripts for testing and benchmarking the flash +proxy.
-This README contains descriptions of each numbered experiment. +== Preparation
-Experiment -00 - Includes socat, crossdomaind, swfcat, httpd, and facilitator +You need to have installed certain software before running the tests. + Firefox + socat + Wget + Python + thttpd + Flash Player +Firefox, socat, Wget, and Python are easily installed on most GNU/Linux +distributions. thttpd can be compiled from the packages at +http://acme.com/software/thttpd/. A debug version of Flash Player can be +downloaded from http://www.adobe.com/support/flashplayer/downloads.html. + +You need to create some dedicated Firefox profiles. Create profiles +named flashexp1 and flashexp2 by running + firefox -ProfileManager -no-remote +Start the browsers with + firefox -P flashexp1 -no-remote & + firefox -P flashexp2 -no-remote & +and in each one, set this about:config variable: + browser.link.open_newwindow=1 (default is 3) +This allows the scripts to clear the contents of a tab and replace them +with another page. + +Before running any tests, start the crossdomain server as root: + sudo crossdomaind.py --daemon +The tests themselves shouldn't be run as root. + +I personally run these tests in an Arch Linux VM. + useradd -m user + passwd user + pacman -Sy + pacman -Su + pacman -S firefox socat python2 xorg xorg-xinit xterm flashplugin gcc make +Download thttpd, compile it (you have to rename the getline function to +avoid a naming conflict), and install it in /usr/local/bin. Symlink +/usr/bin/python to /usr/bin/python2. Also you have to install the +ttf-ms-fonts package from the AUR for text to show up in Flash Player. +Add a window manager, run "startx", and you should be set. diff --git a/experiments/common.sh b/experiments/common.sh new file mode 100644 index 0000000..485e908 --- /dev/null +++ b/experiments/common.sh @@ -0,0 +1,34 @@ +# This file contains common variables and subroutines used by the experiment +# scripts. + +FIREFOX=firefox +SOCAT=socat +THTTPD=thttpd + +visible_sleep() { + N="$1" + echo -n "sleep $N" + while [ "$N" -gt 0 ]; do + sleep 1 + N=$((N-1)) + echo -ne "\rsleep $N" + done + echo -ne "\n" +} + +ensure_browser_started() { + local PROFILE="$1" + ("$FIREFOX" -P "$PROFILE" -remote "ping()" || "$FIREFOX" -P "$PROFILE" -no-remote & visible_sleep 5) 2>/dev/null +} + +browser_clear() { + local PROFILE="$1" + ("$FIREFOX" -P "$PROFILE" -remote "ping()" && "$FIREFOX" -P "$PROFILE" -remote "openurl(about:blank)" &) 2>/dev/null +} + +browser_goto() { + local PROFILE="$1" + local URL="$2" + ensure_browser_started "$PROFILE" + "$FIREFOX" -P "$PROFILE" -remote "openurl($URL)" 2>/dev/null +} diff --git a/experiments/throughput/throughput-all.sh b/experiments/throughput/throughput-all.sh new file mode 100755 index 0000000..015e3e1 --- /dev/null +++ b/experiments/throughput/throughput-all.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +for n in $(seq 1 50); do + ./throughput.sh -n $n +done diff --git a/experiments/throughput/throughput.sh b/experiments/throughput/throughput.sh new file mode 100755 index 0000000..5e2fd4b --- /dev/null +++ b/experiments/throughput/throughput.sh @@ -0,0 +1,105 @@ +#!/bin/sh + +# Usage: ./throughput.sh [-n NUM_CLIENTS] +# +# Tests the raw throughput of a single proxy. This script starts a web server +# serving swfcat.swf and a large data file, starts a facilitator, connector, and +# socat shim, and then starts multiple downloads through the proxy at once. +# Results are saved in a file called results-NUM_CLIENTS-DATE, where DATE is the +# current date. + +. ../common.sh + +FLASHPROXY_DIR=../../../flashproxy + +NUM_CLIENTS=1 + +while getopts "n:" OPTNAME; do + if [ "$OPTNAME" == n ]; then + NUM_CLIENTS="$OPTARG" + fi +done + +PROFILE=flashexp1 +PROXY_URL="http://localhost:8000/swfcat.swf?facilitator=127.0.0.1:9002&max_clients=..." +DATA_FILE_NAME="$FLASHPROXY_DIR/dump" +RESULTS_FILE_NAME="results-$NUM_CLIENTS-$(date --iso)" + +# Declare an array. +declare -a PIDS_TO_KILL +stop() { + browser_clear "$PROFILE" + if [ -n "${PIDS_TO_KILL[*]}" ]; then + echo "Kill pids ${PIDS_TO_KILL[@]}." + kill "${PIDS_TO_KILL[@]}" + fi + echo "Delete data file." + rm -f "$DATA_FILE_NAME" + exit +} +trap stop EXIT + +echo "Create data file." +dd if=/dev/null of="$DATA_FILE_NAME" bs=1M seek=100 2>/dev/null || exit + +echo "Start web server." +"$THTTPD" -D -d "$FLASHPROXY_DIR" -p 8000 & +PIDS_TO_KILL+=($!) + +echo "Start facilitator." +"$FLASHPROXY_DIR"/facilitator.py -d --relay 127.0.0.1:8000 >/dev/null & +PIDS_TO_KILL+=($!) +visible_sleep 1 + +echo "Start connector." +"$FLASHPROXY_DIR"/connector.py >/dev/null & +PIDS_TO_KILL+=($!) +visible_sleep 1 + +echo "Start browser." +browser_goto "$PROFILE" "$PROXY_URL" +visible_sleep 2 + +# Create sufficiently many client registrations. +i=0 +while [ $i -lt $NUM_CLIENTS ]; do + echo -ne "\rRegister client $((i + 1))." + echo $'POST / HTTP/1.0\r\n\r\nclient=127.0.0.1:9000' | socat STDIN TCP-CONNECT:localhost:9002 + sleep 1 + i=$((i + 1)) +done +echo +visible_sleep 2 + +echo "Start socat." +"$SOCAT" TCP-LISTEN:2000,fork,reuseaddr SOCKS4A:localhost:dummy:0,socksport=9001 & +PIDS_TO_KILL+=($!) +visible_sleep 1 + + +# Extract and parse the "real" part of "time" output and return as a count of +# seconds. +extract_real_time() { + perl -n -e '($m, $s) = ($_ =~ m/real\s+(\d+)m([\d.]+)s/); if (defined($m)) { print $m*60 + $s . "\n"; }' +} + +> "$RESULTS_FILE_NAME" + +declare -a WAIT_PIDS +i=0 +while [ $i -lt $NUM_CLIENTS ]; do + echo "Start Wget $((i + 1))." + ( + times=$((time wget http://localhost:2000/dump -q --timeout 30 -t 1 -O /dev/null) 2>&1) + if [ $? -eq 0 ]; then + echo "$times" | extract_real_time >> "$RESULTS_FILE_NAME" + else + echo "error" >> "$RESULTS_FILE_NAME" + fi + ) & + WAIT_PIDS+=($!) + i=$((i + 1)) +done +for pid in "${WAIT_PIDS[@]}"; do + wait "$pid" +done