Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add scripts to ease performance graph generation #3607

Merged
merged 1 commit into from
Aug 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 133 additions & 0 deletions perf/generate_csv.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/bin/bash

#
# This script assumes that 2 machines are used to generate performance results.
# First machine is assumed to be the one where this script runs.
# Second machine is the "REMOTE_IP" machine; we assume to have passwordless SSH access.
#

set -u

# configurable values:
REMOTE_IP=${REMOTE_IP:-127.0.0.1}
REMOTE_PATH=/home/francesco/work/libzmq-orig/perf #/root/libzmq/perf
TEST_ENDPOINT=tcp://127.0.0.1:1234
MESSAGE_SIZE_LIST="1 16 64 128 512 1024 4096 16384 65536"
OUTPUT_FILE_PREFIX="results.txt"
OUTPUT_FILE_CSV_PREFIX="results.csv"


# utility functions:

function verify_ssh()
{
ssh $REMOTE_IP "ls /" >/dev/null
if [ $? -ne 0 ]; then
echo "Cannot connect via SSH passwordless to the REMOTE_IP $REMOTE_IP. Please fix the problem and retry."
exit 2
fi

ssh $REMOTE_IP "ls $REMOTE_PATH" >/dev/null
if [ $? -ne 0 ]; then
echo "The folder $REMOTE_PATH is not valid. Please fix the problem and retry."
exit 2
fi

echo "SSH connection to the remote $REMOTE_IP is working fine."
}

function run_remote_perf_util()
{
local MESSAGE_SIZE_BYTES="$1"
local REMOTE_PERF_UTIL="$2"
local NUM_MESSAGES="$3"

echo "Launching on $REMOTE_IP the utility [$REMOTE_PERF_UTIL] for messages ${MESSAGE_SIZE_BYTES}B long"
ssh $REMOTE_IP "$REMOTE_PATH/$REMOTE_PERF_UTIL $TEST_ENDPOINT $MESSAGE_SIZE_BYTES $NUM_MESSAGES" &
if [ $? -ne 0 ]; then
echo "Failed to launch remote perf util."
exit 2
fi
}

function generate_output_file()
{
local LOCAL_PERF_UTIL="$1" # must be the utility generating the TXT output
local REMOTE_PERF_UTIL="$2"
local OUTPUT_FILE_PREFIX="$3"
local NUM_MESSAGES="$4"
local CSV_HEADER_LINE="$5"

# derived values:
local OUTPUT_FILE_TXT="${OUTPUT_FILE_PREFIX}.txt" # useful just for human-friendly debugging
local OUTPUT_FILE_CSV="${OUTPUT_FILE_PREFIX}.csv" # actually used to later produce graphs
local MESSAGE_SIZE_ARRAY=($MESSAGE_SIZE_LIST)

echo "Killing still-running ZMQ performance utils, if any"
pkill $LOCAL_PERF_UTIL # in case it's running from a previous test
if [ ! -z "$REMOTE_PERF_UTIL" ]; then
ssh $REMOTE_IP "pkill $REMOTE_PERF_UTIL" # in case it's running from a previous test
fi

echo "Resetting output file $OUTPUT_FILE_TXT and $OUTPUT_FILE_CSV"
> $OUTPUT_FILE_TXT
echo "$CSV_HEADER_LINE" > $OUTPUT_FILE_CSV

for MESSAGE_SIZE in ${MESSAGE_SIZE_ARRAY[@]}; do
echo "Launching locally the utility [$LOCAL_PERF_UTIL] for messages ${MESSAGE_SIZE}B long"
./$LOCAL_PERF_UTIL $TEST_ENDPOINT $MESSAGE_SIZE $NUM_MESSAGES >${OUTPUT_FILE_TXT}-${MESSAGE_SIZE} &

if [ ! -z "$REMOTE_PERF_UTIL" ]; then
run_remote_perf_util $MESSAGE_SIZE $REMOTE_PERF_UTIL $NUM_MESSAGES
fi
wait

# produce the complete human-readable output file:
cat ${OUTPUT_FILE_TXT}-${MESSAGE_SIZE} >>${OUTPUT_FILE_TXT}

# produce a machine-friendly file for later plotting:
local DATALINE="$(cat ${OUTPUT_FILE_TXT}-${MESSAGE_SIZE} | grep -o '[0-9.]*' | tr '\n' ',')"
echo ${DATALINE::-1} >>$OUTPUT_FILE_CSV
rm -f ${OUTPUT_FILE_TXT}-${MESSAGE_SIZE}
done

echo "All measurements completed and saved into $OUTPUT_FILE_TXT and $OUTPUT_FILE_CSV"
}



# main:

verify_ssh

THROUGHPUT_CSV_HEADER_LINE="# message_size,message_count,PPS[msg/s],throughput[Mb/s]"

# PUSH/PULL TCP throughput CSV file:
generate_output_file "local_thr" "remote_thr" \
"pushpull_tcp_thr_results" \
"100000" \
"$THROUGHPUT_CSV_HEADER_LINE"

# PUSH/PULL INPROC throughput CSV file:
# NOTE: in this case there is no remote utility to run and no ENDPOINT to provide:
TEST_ENDPOINT=""
generate_output_file "inproc_thr" "" \
"pushpull_inproc_thr_results" \
"1000000" \
"$THROUGHPUT_CSV_HEADER_LINE"

# PUB/SUB proxy INPROC throughput CSV file:
# NOTE: in this case there is no remote utility to run and no ENDPOINT to provide:
TEST_ENDPOINT=""
generate_output_file "proxy_thr" "" \
"pubsubproxy_inproc_thr_results" \
"1000000" \
"$THROUGHPUT_CSV_HEADER_LINE"


# REQ/REP TCP latency CSV file:
# NOTE: in this case it's the remote_lat utility that prints out the data, so we swap the local/remote arguments to the bash func:
generate_output_file "remote_lat" "local_lat" \
"reqrep_tcp_lat_results" \
"10000" \
"# message_size,message_count,latency[us]"
49 changes: 49 additions & 0 deletions perf/generate_graphs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#!/usr/bin/python

#
# This script assumes that a CSV file produced by "generate_csv.sh" is provided as input
#

# configurable values:
INPUT_FILE_PUSHPULL_TCP_THROUGHPUT="pushpull_tcp_thr_results.csv"
INPUT_FILE_PUSHPULL_INPROC_THROUGHPUT="pushpull_inproc_thr_results.csv"
INPUT_FILE_PUBSUBPROXY_INPROC_THROUGHPUT="pubsubproxy_inproc_thr_results.csv"
INPUT_FILE_REQREP_TCP_LATENCY="reqrep_tcp_lat_results.csv"


# dependencies

import matplotlib.pyplot as plt
import numpy as np


# functions

def plot_throughput(csv_filename, title):
message_size_bytes, message_count, pps, mbps = np.loadtxt(csv_filename, delimiter=',', unpack=True)
plt.semilogx(message_size_bytes, pps / 1e6, label='PPS [Mmsg/s]', marker='x')
plt.semilogx(message_size_bytes, mbps / 1e3, label='Throughput [Mb/s]', marker='o')

plt.xlabel('Message size [B]')
plt.title(title)
plt.legend()
plt.show()
plt.savefig(csv_filename.replace('.csv', '.png'))

def plot_latency(csv_filename, title):
message_size_bytes, message_count, lat = np.loadtxt(csv_filename, delimiter=',', unpack=True)
plt.semilogx(message_size_bytes, lat, label='Latency [us]', marker='o')

plt.xlabel('Message size [B]')
plt.title(title)
plt.legend()
plt.show()
plt.savefig(csv_filename.replace('.csv', '.png'))


# main

plot_throughput(INPUT_FILE_PUSHPULL_TCP_THROUGHPUT, 'ZeroMQ PUSH/PULL socket throughput, TCP transport')
plot_throughput(INPUT_FILE_PUSHPULL_INPROC_THROUGHPUT, 'ZeroMQ PUSH/PULL socket throughput, INPROC transport')
plot_throughput(INPUT_FILE_PUBSUBPROXY_INPROC_THROUGHPUT, 'ZeroMQ PUB/SUB PROXY socket throughput, INPROC transport')
plot_latency(INPUT_FILE_REQREP_TCP_LATENCY, 'ZeroMQ REQ/REP socket latency, TCP transport')
8 changes: 4 additions & 4 deletions perf/proxy_thr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ static void publisher_thread_main (void *pvoid)
}

zmq_close (pubsocket);
printf ("publisher thread ended\n");
//printf ("publisher thread ended\n");
}

static void subscriber_thread_main (void *pvoid)
Expand Down Expand Up @@ -215,7 +215,7 @@ static void subscriber_thread_main (void *pvoid)
// Cleanup

zmq_close (subsocket);
printf ("subscriber thread ended\n");
//printf ("subscriber thread ended\n");
}

static void proxy_thread_main (void *pvoid)
Expand Down Expand Up @@ -284,7 +284,7 @@ static void proxy_thread_main (void *pvoid)
zmq_close (frontend_xsub);
zmq_close (backend_xpub);
zmq_close (control_rep);
printf ("proxy thread ended\n");
//printf ("proxy thread ended\n");
}

void terminate_proxy (const proxy_hwm_cfg_t *cfg)
Expand Down Expand Up @@ -314,7 +314,7 @@ void terminate_proxy (const proxy_hwm_cfg_t *cfg)
int main (int argc, char *argv[])
{
if (argc != 3) {
printf ("usage: inproc_thr <message-size> <message-count>\n");
printf ("usage: proxy_thr <message-size> <message-count>\n");
return 1;
}

Expand Down