#!/bin/bash

J=~/trunks/shenandoah-jdk11/build/linux-x86_64-normal-server-release/images/jdk/bin/java
J_OPTS="-Xmx1g -Xlog:gc -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions -XX:ConcGCThreads=2 -XX:ParallelGCThreads=2"

W=~/trunks/wrk2/wrk

runWith() {
  $J $J_OPTS $2 $3 $4 $5 $6 $7 $8 -jar target/spring-petclinic-2.1.0.BUILD-SNAPSHOT.jar > /dev/null &
  J_PID=$!

  START=`date +%s.%3N`

  ( while [ -e /proc/$J_PID ]; do
      C=`date +%s.%3N`
      TS=`echo "$C - $START" | bc -l`
      echo -n "$TS " >> $1
      cat /proc/$J_PID/status | grep VmRSS | awk '{ print $2; }'>> $1
      sleep 0.1
    done
  ) &
  S_PID=$!

  ( while [ -e /proc/$J_PID ]; do
      C=`date +%s.%3N`
      TS=`echo "$C - $START" | bc -l`
      echo -n "$TS " >> $1.cpu
      cat /proc/$J_PID/stat | awk '{ print $14; }' >> $1.cpu
      sleep 0.5
    done
  ) &
  SC_PID=$!

  ( while [ -e /proc/$J_PID ]; do
      C=`date +%s.%3N`
      TS=`echo "$C - $START" | bc -l`
      YGC=`jstat -gcutil local://$J_PID 2>&1 | tail -n 1 | awk '{ print $7; }' | tr '-' '0'`
      FGC=`jstat -gcutil local://$J_PID 2>&1 | tail -n 1 | awk '{ print $9; }' | tr '-' '0'`
      GC=`echo "$YGC + $FGC" | bc -l`
      echo "$TS $GC" >> $1.gc
      sleep 0.5
    done
  ) &
  SG_PID=$!

  sleep 20

  $W -c 16 -t 16 -d 20 -R 1000 http://localhost:8080/

  sleep 20

  for GC in `seq 1 5`; do
    jcmd $J_PID GC.run
    sleep 1
  done

  sleep 10

  kill $S_PID
  kill $SC_PID
  kill $SG_PID
  kill $J_PID
}

# Very short runs, need to trim down ShenandoahGuaranteedGCInterval and ShenandoahUncommitDelay from their default 5 minutes.
# "compact" does trim them down, but not to the values we want for this test.
rm *.data*
runWith 1.data -XX:+UseSerialGC
runWith 2.data -XX:+UseG1GC
runWith 3.data -XX:+UseShenandoahGC -XX:ShenandoahGuaranteedGCInterval=5000 -XX:ShenandoahUncommitDelay=5000
runWith 4.data -XX:+UseShenandoahGC -XX:ShenandoahGuaranteedGCInterval=5000 -XX:ShenandoahGCHeuristics=compact 

cat > plot.gnu << EOL
set term svg size 1200,800 linewidth 3 font "Helvetica,24"
set border 0

set key outside below
set grid xtics ytics
set xlabel "time, sec"
set ylabel "RSS, MB"

set grid xtics ytics mxtics mytics lc '#BBBBBB'
set key outside bottom box lw 1 lc '#AAAAAA'

set xrange [0:75]
set xtics 10
set mxtics 10

# line styles
set style line 1 lw 2 lt 1 lc rgb '#0072bd' # blue
set style line 4 lw 2 lt 1 lc rgb '#d95319' # orange
set style line 2 lw 2 lt 1 lc rgb '#edb120' # yellow
set style line 3 lw 2 lt 1 lc rgb '#77ac30' # green
set style line 5 lw 2 lt 1 lc rgb '#7e2f8e' # purple
set style line 6 lw 2 lt 1 lc rgb '#4dbeee' # light-blue
set style line 7 lw 2 lt 1 lc rgb '#a2142f' # red

# palette
set palette maxcolors 8
set palette defined ( 0 '#1B9E77',\
    	    	      1 '#D95F02',\
		      2 '#7570B3',\
		      3 '#E7298A',\
		      4 '#66A61E',\
		      5 '#E6AB02',\
		      6 '#A6761D',\
		      7 '#666666' )

set yrange [0:1600]
set ytics 400
set mytics 5

set arrow 1 from 6,0 to 6,1600 nohead
set arrow 2 from 20,0 to 20,1600 nohead
set arrow 3 from 40,0 to 40,1600 nohead
set arrow 4 from 60,0 to 60,1600 nohead
set arrow 5 from 65,0 to 65,1600 nohead

set label 1 "Start" at 1, 1520
set label 2 "Idle" at 11, 1520
set label 3 "Load" at 28, 1520
set label 4 "Idle" at 49, 1520
set label 5 "GC()" at 61, 1520
set label 6 "Idle" at 68, 1520


set title "spring-boot-petclinic, wrk2 http test, 1000 RPS, OpenJDK 11 x86-64, -Xmx1g"

set output "out-memory.svg"
plot '1.data' using (\$1):(\$2/1000) with lines ls 1 title 'Serial', \
     '2.data' using (\$1):(\$2/1000) with lines ls 2 title 'G1', \
     '3.data' using (\$1):(\$2/1000) with lines ls 3 title 'Shenandoah (default)', \
     '4.data' using (\$1):(\$2/1000) with lines ls 4 title 'Shenandoah (compact)'

old_v = NaN
min(a,b) = a >= b ? b : a
samples(n) = min(int(\$0), n)
avg_data = ""

sum_n(data, n) = ( n <= 0 ? 0 : word(data, words(data) - n) + sum_n(data, n - 1))

avg(x, n) = ( avg_data = sprintf("%s %f", (int(\$0)==0)?"":avg_data, x), sum_n(avg_data, samples(n))/samples(n)) 

delta_v(x) = ( vD = x - old_v, old_v = x, vD)


set ylabel "GC invocations, #/sec"

set arrow 1 from 6,0 to 6,24 nohead
set arrow 2 from 20,0 to 20,24 nohead
set arrow 3 from 40,0 to 40,24 nohead
set arrow 4 from 60,0 to 60,24 nohead
set arrow 5 from 65,0 to 65,24 nohead

set label 1 "Start" at 1, 22
set label 2 "Idle" at 11, 22
set label 3 "Load" at 28, 22
set label 4 "Idle" at 49, 22
set label 5 "GC()" at 61, 22
set label 6 "Idle" at 68, 22

set yrange [0:24]
#set log y
set ytics 4
set mytics 4

# Shenandoah jstat reports 4 pauses, while it is actually a single GC

set output "out-gc.svg"
plot \
     '1.data.gc' using (\$1):(delta_v(\$2))   with lines ls 1 title 'Serial', \
     '2.data.gc' using (\$1):(delta_v(\$2))   with lines ls 2 title 'G1', \
     '3.data.gc' using (\$1):(delta_v(\$2/4)) with lines ls 3 title 'Shenandoah (default)', \
     '4.data.gc' using (\$1):(delta_v(\$2/4)) with lines ls 4 title 'Shenandoah (compact)'
     
old_v = NaN

set ylabel "Java user CPU, %"

set yrange [0:800]
set ytics 200
set mytics 5

set arrow 1 from 6,0 to 6,800 nohead
set arrow 2 from 20,0 to 20,800 nohead
set arrow 3 from 40,0 to 40,800 nohead
set arrow 4 from 60,0 to 60,800 nohead
set arrow 5 from 65,0 to 65,800 nohead

set label 1 "Start" at 1, 720
set label 2 "Idle" at 11, 720
set label 3 "Load" at 28, 720
set label 4 "Idle" at 49, 720
set label 5 "GC()" at 61, 720
set label 6 "Idle" at 68, 720

set output "out-cpu.svg"
plot \
     '1.data.cpu' using (\$1):(delta_v(\$2)) with lines ls 1 title 'Serial', \
     '2.data.cpu' using (\$1):(delta_v(\$2)) with lines ls 2 title 'G1', \
     '3.data.cpu' using (\$1):(delta_v(\$2)) with lines ls 3 title 'Shenandoah (default)', \
     '4.data.cpu' using (\$1):(delta_v(\$2)) with lines ls 4 title 'Shenandoah (compact)'

old_v = NaN

EOL

gnuplot plot.gnu

