diff --git a/extras/dialer/.gitignore b/extras/dialer/.gitignore new file mode 100644 index 0000000000..e660fd93d3 --- /dev/null +++ b/extras/dialer/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/extras/dialer/Dockerfile b/extras/dialer/Dockerfile new file mode 100644 index 0000000000..942f2c4eff --- /dev/null +++ b/extras/dialer/Dockerfile @@ -0,0 +1,2 @@ +FROM golang:1.7 +ADD ./bin/dialer /go/bin diff --git a/extras/dialer/README.md b/extras/dialer/README.md new file mode 100644 index 0000000000..8e67cafd1c --- /dev/null +++ b/extras/dialer/README.md @@ -0,0 +1,46 @@ +## Overview + +The dialer scripts can be used to test Scope with a high number of +containers and connections. + +The dialer server is a TCP server that holds incoming connections +forever. + +The dialer client is a TCP client that opens n connection to a server +and holds them forever. + +The `listener` script starts a dialer server and prints its address for +usage with the `dialer` script. The `dialer` scripts starts up to n +(default 50) client containers, each opening a random (1-20) number of +connections. + +`time-scope-probe` then can be used to measure the scheduled time +(utime + stime) of the scope-probe process on the host. The results +can be used to compare performance under different scenarios/branches. + +## Usage example + +``` +# Start a listener +./tools/dialer/listener +Listening on :8082 +IP addr + port: 172.17.0.2:8082 + + +# Start the dialer script with a maximum of 10 dialer containers +# (default 50) +./tools/dialer/dialer 172.17.0.2:8082 10 + + +# Start time-scope-probe to measure the scheduled time of scope-probe +# every 3 seconds (default 10 seconds) for 3 times (default 60 times) +sudo ./tools/dialer/time-scope-probe 3 3 +... +``` + +## Build dialer container + +``` +go build -o bin/dialer +docker build -t dialer . +``` diff --git a/extras/dialer/dialer b/extras/dialer/dialer new file mode 100755 index 0000000000..a14d9d798a --- /dev/null +++ b/extras/dialer/dialer @@ -0,0 +1,26 @@ +#!/bin/bash +set -eu +if [ $# -lt 1 ]; then + echo "Usage: $0 []" >&2 + exit 1 +fi + +readonly addr=$1 +readonly max_dialer=${2:-50} + +dialer=() +trap 'echo -n "stopping ... "; for c in "${dialer[@]}"; do docker rm -f "$c" >/dev/null; done; echo "done"' EXIT + +while true; do + rand=$(( ( RANDOM % max_dialer ) + 1 )) + dialer+=("$(docker run -d dialer /go/bin/dialer connect "$addr" "$rand")") + + if [ ${#dialer[@]} -gt "$max_dialer" ]; then + container=${dialer[$rand]} + docker rm -f "$container" >/dev/null & + unset dialer[$rand] + dialer=("${dialer[@]}") + fi + + sleep $(( rand % 3 )) +done diff --git a/extras/dialer/dialer.go b/extras/dialer/dialer.go new file mode 100644 index 0000000000..3eef4a66f8 --- /dev/null +++ b/extras/dialer/dialer.go @@ -0,0 +1,76 @@ +package main + +import ( + "fmt" + "net" + "os" + "strconv" +) + +func connect(url string, numConn int) { + fmt.Printf("Establishing %d TCP connections to %s\n", numConn, url) + for x := 0; x < numConn; x++ { + _, err := net.Dial("tcp", url) + + if err != nil { + fmt.Printf("Error: %v\n", err) + os.Exit(1) + } + } + + // wait forever + select {} +} + +func listen(url string) { + l, err := net.Listen("tcp", url) + if err != nil { + fmt.Println("Error listening:", err.Error()) + os.Exit(1) + } + defer l.Close() + fmt.Println("Listening on " + url) + for { + _, err := l.Accept() + if err != nil { + fmt.Println("Error accepting: ", err.Error()) + os.Exit(1) + } + } + +} + +func main() { + if len(os.Args) < 2 { + fmt.Println("Not enough arguments") + os.Exit(1) + } + + verb := os.Args[1] + + if verb == "connect" { + if len(os.Args) != 4 { + fmt.Println("Not enough arguments") + os.Exit(1) + } + + url := os.Args[2] + numConn, err := strconv.Atoi(os.Args[3]) + if err != nil { + fmt.Printf("Error with second argument\n") + os.Exit(1) + } + + connect(url, numConn) + } + if verb == "listen" { + if len(os.Args) != 3 { + fmt.Println("Not enough arguments") + os.Exit(1) + } + + port := os.Args[2] + listen(":" + port) + } + +} diff --git a/extras/dialer/listener b/extras/dialer/listener new file mode 100755 index 0000000000..7e6112a67d --- /dev/null +++ b/extras/dialer/listener @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu +readonly port=${1:-8082} +( +sleep 5 # wait for dialerserver to start +echo "IP addr + port: $(docker inspect -f '{{ .NetworkSettings.IPAddress }}' dialerserver):$port" +) & +docker run --rm --name dialerserver dialer /go/bin/dialer listen "$port" diff --git a/extras/dialer/time-scope-probe b/extras/dialer/time-scope-probe new file mode 100755 index 0000000000..bc28644fd6 --- /dev/null +++ b/extras/dialer/time-scope-probe @@ -0,0 +1,33 @@ +#!/bin/bash +set -eu +if [ $EUID -ne 0 ]; then + echo "You must be root!" >&2 + exit 1 +fi + +readonly interval_num=${1:-60} +readonly interval_sleep=${2:-10} + +TIME_U1=0 +TIME_K1=0 +TIME_T1=0 +TIME_U2=0 +TIME_K2=0 +TIME_T2=0 + +if [ "$(pidof scope-probe)" == "" ]; then + echo "No scope-probe process running - aborting" >&2 + exit 1 +fi + +for ((i=0; i<"$interval_num"; i++)); do + sleep "$interval_sleep" + TIME_U1=$TIME_U2 + TIME_K1=$TIME_K2 + TIME_T1=$TIME_T2 + + TIME_U2=$(gawk '{print $14"*10"}'<"/proc/$(pidof scope-probe)/stat" | bc) + TIME_K2=$(gawk '{print $15"*10"}'<"/proc/$(pidof scope-probe)/stat" | bc) + TIME_T2=$(( TIME_U2 + TIME_K2 )) + echo "utime $(( TIME_U2 - TIME_U1)) + stime $(( TIME_K2 - TIME_K1 )) = $(( TIME_T2 - TIME_T1 ))" +done