#!/bin/bash # Reproduce the Duoram experiments from our paper: # Sajin Sasy, Adithya Vadapalli, Ian Goldberg. PRAC: Round-Efficient # 3-Party MPC for Dynamic Data Structures # cd into the directory containing this script (from the bash faq 028) if [[ $BASH_SOURCE = */* ]]; then cd -- "${BASH_SOURCE%/*}/" || exit fi # If the PRAC NUMA commands are set, use them for Duoram if [ "$PRAC_NUMA_P0" != "" ]; then export DUORAM_NUMA_P0="$PRAC_NUMA_P0" fi if [ "$PRAC_NUMA_P1" != "" ]; then export DUORAM_NUMA_P1="$PRAC_NUMA_P1" fi if [ "$PRAC_NUMA_P2" != "" ]; then export DUORAM_NUMA_P2="$PRAC_NUMA_P2" fi # If the PRAC memory usage is set, use it for Duoram. In Duoram, P2 uses # twice the memory of P0 or P1 for preprocessing, so if P0 and P2 are on # the same NUMA node, set the total RAM available to 4/3 of the RAM # available for that node. if [ "$PRAC_P0_MAXGB" != "" ]; then export DUORAM_MAXGB=$((2*PRAC_P0_MAXGB)) elif [ "$PRAC_P02_MAXGB" != "" ]; then export DUORAM_MAXGB=$((4*PRAC_P02_MAXGB/3)) elif [ "$PRAC_MAXGB" != "" ]; then export DUORAM_MAXGB=$PRAC_MAXGB fi # Allow running only subsets of the experiment suite. Valid values are # "test", "fig6", "all", "none". ("none" is useful if you just want to # re-parse the output of existing logs.) You can also say "single" # followed by all the arguments to "run" (below) to run a single # experiment; for example: # ./repro single readwrite 20 1us 100gbit 128 if [ "$1" = "" ]; then whichexps="test" else whichexps="$1" fi # The number of iterations per run; the graphs in the paper use 3 if [ "$whichexps" = "single" -o "$2" = "" ]; then # If there's an explicit experiment on the command line, don't read # the next argument as the number of operations. $numiters will be # ignored, anyway, since it will be specified as part of the # command. numiters=3 else numiters="$2" fi # The maximum amount of memory to use (in GB). Set the environment # variable DUORAM_MAXGB to increase it beyond 16 (don't set it lower # than 16). if [ "$DUORAM_MAXGB" = "" ]; then maxgb=16 elif [ "$DUORAM_MAXGB" -gt 16 ]; then maxgb=$DUORAM_MAXGB else maxgb=16 fi # Run one experiment # Arguments: # $1: mode (read, write, readwrite) # $2: depth (the ORAM has 2^depth elements) # $3: latency (e.g., 30ms) # $4: bandwidth (e.g., 100mbit) # $5: number of operations (e.g., 128) # $6: phase (preproc or online) # $7: number of parties (3P or 2P) runone() { now=`date` echo "$now: Running $1 $2 $3 $4 $5 $6 $7 ..." logfile="${1}_${3}_${4}_${5}_${6}_${7}.out${LOGSUFFIX}" ./set-networking $3 $4 echo "Max GB: $maxgb" >> $logfile echo "Network setup: $3 $4" >> $logfile ./run-experiment $1 $2 $5 $6 $7 $maxgb >> $logfile } # Run one set of Duoram experiments: 2P and 3P, read and write, # preprocessing and online # Arguments: # $1: depth (the ORAM has 2^depth elements) # $2: latency (e.g., 30ms) # $3: bandwidth (e.g., 100mbit) # $4: number of operations (e.g., 128) run() { # The 3P preprocessing protocol is identical for reads and writes, # so we just do it once, and count it twice for readwrite. runone read $1 $2 $3 $4 preproc 3P # The 3P online protocols do reads, writes, and readwrites in a # single run. runone readwrite $1 $2 $3 $4 online 3P # Clean up any preprocessed DPFs docker exec -w /root/duoram/duoram-online/preprocflags duoram_p0 bash -c "rm -f *" & docker exec -w /root/duoram/duoram-online/preprocflags duoram_p1 bash -c "rm -f *" & docker exec -w /root/duoram/duoram-online/preprocflags duoram_p2 bash -c "rm -f *" & wait } # Parse the output logs. We run this in the docker in case you don't # have perl installed on the host. # Arguments: a list of logfiles parse() { if [ "$DUORAM_PARSE_HOST" = "1" ]; then ./parse_logs $* else cat $* | docker exec -w /root/duoram/Docker -i duoram_p0 ./parse_logs fi } # A very small kick-the-tires test to ensure everything compiled and # built properly if [ "$whichexps" = "test" ]; then echo "Running test experiment..." run 16 1us 100gbit 2 echo echo "# Test output" echo parse \ read_1us_100gbit_2_preproc_3P.out${LOGSUFFIX} \ readwrite_1us_100gbit_2_online_3P.out${LOGSUFFIX} \ | egrep '(Onln|Totl).*readwrite' | sort echo echo "# End test output" echo exit fi # Be able to run a single experiment specified on the command line if [ "$whichexps" = "single" ]; then echo "Running single experiment..." shift runone $* exit fi now=`date` echo "$now: Starting experiments" if [ "$whichexps" = "fig6" -o "$whichexps" = "all" ]; then echo "Running Figure 6 experiments..." for i in $(seq 1 $numiters); do # Figure 6(a) for nops in 16 32 64 128 256 512 1024 2048; do run 20 30ms 100mbit $nops done if [ "$maxgb" -gt 164 ]; then large_exps="28 30" elif [ "$maxgb" -gt 41 ]; then large_exps="28" else large_exps="" fi # Figures 6(b), 6(c) for size in 16 18 20 22 24 26 ${large_exps}; do run $size 30ms 100mbit 10 done done fi now=`date` echo "$now: Experiments complete" # If you specified a custom log suffix, you're going to be parsing the # outputs differently. if [ "$LOGSUFFIX" = "" ]; then parse *_{online,preproc}_3P.out > duoram.dat echo echo "# Figure 6(a)" egrep '3PDuoramTotl read 20 30ms 100mbit (16|32|64|128|256|512|1024|2048) .* s$' duoram.dat | sort -k6 -n #echo #egrep '3PDuoramOnln read 20 30ms 100mbit (16|32|64|128|256|512|1024|2048) .* s$' duoram.dat | sort -k6 -n echo echo "# Figure 6(b)" egrep '3PDuoramTotl read .* 30ms 100mbit 10 .* s$' duoram.dat | sort -k3 -n echo #egrep '3PDuoramOnln read .* 30ms 100mbit 10 .* s$' duoram.dat | sort -k3 -n #echo echo "# Figure 6(c)" egrep '3PDuoramTotl read .* 30ms 100mbit 10 .* KiB$' duoram.dat | sort -k3 -n echo #egrep '3PDuoramOnln read .* 30ms 100mbit 10 .* KiB$' duoram.dat | sort -k3 -n #echo echo "# End figures" echo fi