#!/bin/bash
# Usage: [RAMCLOUD_DIR=rc_dir] run_workload.sh {W1|W2|...} num_nodes duration
#
# Run the echo_workload experiment in ClusterPerf using the given workload
# with `num_nodes` machines for `duration` seconds; generate the message
# slowdown plots used in the Homa paper. The RAMCloud's top directory can be
# specified via environment variable RAMCLOUD_DIR; otherwise, it is assumed
# that the current working directory is the RAMCloud's top directory.

# Change the current working directory to RAMCloud's top directory.
[[ -v RAMCLOUD_DIR ]] && cd $RAMCLOUD_DIR
[[ ! -f scripts/clusterperf.py ]] &&
        printf "clusterperf.py not found!\n" && exit

# Set paths to various files and directories
workload=$1
num_nodes=$2
duration=$3
workload_cdf=benchmarks/homa/messageSizeCDFs/${workload}.txt    # Workload message size CDF file
config_dir=config                                               # RAMCloud's config directory
transport_config=$config_dir/transport.txt                      # Transport config file; hardcoded in XXXTransport.cc
out_dir=homa_experiment_$(date '+%Y%m%d%H%M%S')                 # Output directory containing files generated by this script
rpc_slowdown_data=slowdownImpl.txt                              # Output file containing RPC slowdown numbers
                                                                # Do not change; hardcoded in slowdownImpl.r
compute_slowdown=benchmarks/homa/scripts/compute_slowdown.py    # Script used to compute RPC slowdowns
plot_slowdown=benchmarks/homa/scripts/slowdownImpl.r            # R script used to generate RPC slowdown plots

# Test the existence of prerequesite files.
[[ ! -f $workload_cdf ]] &&
    printf "Wordload message size CDF file not found: $workload_cdf\n" && exit
[[ ! -f $compute_slowdown ]] &&
    printf "File not found: $compute_slowdown\n" && exit
[[ ! -f $plot_slowdown ]] &&
    printf "File not found: $plot_slowdown\n" && exit

# Encode configurations for different experiments (ordered roughly in
# decreasing slowdown of short messages).
if [ $workload == 'W1' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=1"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=1"
            "rttMicros=8,numPrio=4,unschedPrio=3,degreeOC=1,unschedPrioCutoffs=11.126"
            "rttMicros=8,numPrio=8,unschedPrio=7,degreeOC=1,unschedPrioCutoffs=11.126.279.484.820.1543")
elif [ $workload == 'W2' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=3"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=3"
            "rttMicros=8,numPrio=4,unschedPrio=3,degreeOC=3,unschedPrioCutoffs=269.366"
            "rttMicros=8,numPrio=8,unschedPrio=5,degreeOC=3,unschedPrioCutoffs=269.366.512.2156")
elif [ $workload == 'W3' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=4"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=4"
            "rttMicros=8,numPrio=4,unschedPrio=2,degreeOC=4,unschedPrioCutoffs=469"
            "rttMicros=8,numPrio=8,unschedPrio=4,degreeOC=4,unschedPrioCutoffs=469.5521.15267")
elif [ $workload == 'W4' ] || [ $workload == 'W5' ] || [ $workload == 'W7' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=7"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=7"
            "rttMicros=8,numPrio=4,unschedPrio=1,degreeOC=7"
            "rttMicros=8,numPrio=8,unschedPrio=1,degreeOC=7")
elif [ $workload == 'W6' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=4"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=4"
            "rttMicros=8,numPrio=4,unschedPrio=2,degreeOC=4,unschedPrioCutoffs=3436"
            "rttMicros=8,numPrio=8,unschedPrio=4,degreeOC=4,unschedPrioCutoffs=3436.11175.21047")
elif [ $workload == 'W8' ]
then
    plot_label=(Basic HomaP1 HomaP2 HomaP4 HomaP8)
    protocol=(basic homa homa homa homa)
    driver=(dpdk dpdk dpdk dpdk dpdk)
    params=(""
            "rttMicros=8,numPrio=1,unschedPrio=1,degreeOC=6"
            "rttMicros=8,numPrio=2,unschedPrio=1,degreeOC=6"
            "rttMicros=8,numPrio=4,unschedPrio=2,degreeOC=6,unschedPrioCutoffs=18024"
            "rttMicros=8,numPrio=8,unschedPrio=2,degreeOC=6,unschedPrioCutoffs=18024")
else
    printf "Unknown workload: $workload\n" && exit
fi

# Create the output directory and start the experiments
mkdir $out_dir
cp benchmarks/homa/*_${workload}_baseline.txt $out_dir

num_clients=$((num_nodes/2))
num_servers=$((num_nodes/2))
bandwidthGbps=10
for (( i = 0; i < ${#protocol[@]}; i++ )); do
    transport=${protocol[i]}
    [[ ! -z ${driver[i]} ]] && transport+=+${driver[i]}
    echo $transport:${params[i]} > $transport_config
    baseline_data=${transport}_${workload}_baseline.txt

    for target_tput in 2.9 4.8 7.6; do
        load_factor=`echo $target_tput*$bandwidthGbps/1 | bc`
        echo "====================================="
        printf "Running experiment (%s, %s, %s)\n" "${plot_label[i]}" "$workload" "$load_factor"
        profile=${plot_label[i]}_${workload}_${load_factor}
        experiment_data=${profile}_experiment.txt
        cmd="scripts/clusterperf.py --superuser --dpdkPort 1 --replicas 0 --disjunct --transport $transport --servers $num_servers --clients $num_clients --messageSizeCDF $workload_cdf --seconds $duration --targetTput $target_tput --verbose echo_workload > $out_dir/$experiment_data"
        echo "command: $cmd"
        eval $cmd
        cd $out_dir; ../$compute_slowdown $baseline_data $experiment_data >> $rpc_slowdown_data; cd ..

        # Remove client logs (which can be huge) to save disk space.
        rm -rf logs/latest/client*
    done
done

# Generate the plots
#cd $out_dir; Rscript ../$plot_slowdown; cd ..
