| #!/bin/bash |
| # |
| # Licensed to the Apache Software Foundation (ASF) under one or more |
| # contributor license agreements. See the NOTICE file distributed with |
| # this work for additional information regarding copyright ownership. |
| # The ASF licenses this file to You under the Apache License, Version 2.0 |
| # (the "License"); you may not use this file except in compliance with |
| # the License. You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| set -e |
| |
| BENCHMARKS="BasicWriteTest LoginTest LoginLogoutTest LoginGetRootLogoutTest NamespaceTest NamespaceRegistryTest ReadPropertyTest GetNodeWithAdmin GetNodeWithAnonymous GetDeepNodeTest SetPropertyTest SetMultiPropertyTest SmallFileReadTest SmallFileWriteTest ConcurrentReadTest ConcurrentReadWriteTest ConcurrentWriteReadTest ConcurrentWriteTest SimpleSearchTest UUIDLookupTest SQL2SearchTest DescendantSearchTest SQL2DescendantSearchTest FlatTreeUpdateTest CreateManyChildNodesTest CreateManyNodesTest UpdateManyChildNodesTest TransientManyChildNodesTest ReadDeepTreeTest ConcurrentReadDeepTreeTest ConcurrentReadRandomNodeAndItsPropertiesTest ConcurrentTraversalTest ConcurrentCreateNodesTest SequentialCreateNodesTest ConcurrentFileWriteTest IsNodeTypeTest SetPropertyTransientTest" |
| FIXTURES="Oak-Mongo" |
| |
| RUNTIME=60 |
| THREADS="1" |
| PROFILE=false |
| NUM_ITEMS=1000 |
| |
| RESET='\033[0m' |
| RED='\033[31m' |
| GREEN='\033[32m' |
| YELLOW='\033[33m' |
| |
| me=`basename "$0"` |
| repositoryurl="https://github.com/apache/jackrabbit-oak/archive/jackrabbit-oak-version.tar.gz" |
| |
| function usage() { |
| cat <<-EOF |
| THis script runs a set of benchmarks to compare 2 different versions of the application. The base version is the baseline to be compared with, |
| while the current version is the new version to compare against the baseline. |
| |
| This script will download and build the sources of the software from the repository archive in case they are not present in the local system: |
| $repositoryurl |
| |
| USAGE: $me [OPTIONS] |
| |
| OPTIONS |
| |
| -bv Base version to compare results with. |
| -bp Path to the base version of oak-benchmarks.jar in the local system. If not specified sources will be downloaded and built before execution. |
| -bo Location of an existing benchmarks output log for the base version. If specified this file will be read instead of running the benchmarks for the base version. |
| -bs Path to the base version sources of oak-benchmarks in the local system. If specified, the pom.xml file in this folder will be built using maven instead of downloading the sources. |
| -cv Current version to compare results with baseline. |
| -cp Path to the current version of oak-benchmarks.jar in the local system. If not specified sources will be downloaded and built before execution. |
| -co Location of an existing benchmarks output log for the current version. If specified this file will be read instead of running the benchmarks for the current version. |
| -cs Path to the current version sources of oak-benchmarks in the local system. If specified, the pom.xml file in this folder will be build using maven instead of downloading the sources. |
| |
| -of Folder to save all output files generated and downloaded by the script. If not specified, "./target" will be used. |
| -nc Not colorized output. |
| -do Date in output filenames. |
| |
| --fixtures String containing all the fixtures to be executed. |
| --benchmarks String containing all the benchmarks to be executed. |
| --extraargs String containing all the additional arguments to be passed to the benchmarks. For example: "--mongouri mongodb://127.0.0.1:27017/test" |
| |
| --baseversion Same as -bv |
| --basepath Same as -bp |
| --baseoutput Same as -bo |
| --basesource Same as -bs |
| --currentversion Same as -cv |
| --currentpath Same as -cp |
| --currentoutput Same as -co |
| --currentsource Same as -cs |
| |
| --outputfolder Same as -of |
| --nocolor Same as -nc |
| --dateoutput Same as -do |
| EOF |
| } |
| |
| if [[ $# -lt 1 ]] ; then |
| echo "Error: Incorrect number of arguments." |
| usage |
| exit 1 |
| fi; |
| |
| # Configuring arguments |
| while [[ ${1:0:1} == - ]]; do |
| [[ $1 =~ ^(-h|--help)$ ]] && { usage; exit 0; }; |
| [[ $1 =~ ^(-bv|--baseversion)$ ]] && { baseversion=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-bp|--basepath)$ ]] && { basepath=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-bo|--baseoutput)$ ]] && { baseoutput=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-bs|--basesource)$ ]] && { basesource=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-cv|--currentversion)$ ]] && { currentversion=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-cp|--currentpath)$ ]] && { currentpath=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-co|--currentoutput)$ ]] && { currentoutput=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-cs|--currentsource)$ ]] && { currentsource=$2; shift 2; continue; }; |
| |
| [[ $1 =~ ^(-of|--outputfolder)$ ]] && { outputfolder=$2; shift 2; continue; }; |
| [[ $1 =~ ^(-nc|--nocolor)$ ]] && { nocolor=1; shift 1; continue; }; |
| [[ $1 =~ ^(-do|--dateoutput)$ ]] && { dateoutput=1; shift 1; continue; }; |
| |
| [[ $1 =~ ^(--fixtures)$ ]] && { fixtures=$2; shift 2; continue; }; |
| [[ $1 =~ ^(--benchmarks)$ ]] && { benchmarks=$2; shift 2; continue; }; |
| [[ $1 =~ ^(--extraargs)$ ]] && { extraargs=$2; shift 2; continue; }; |
| |
| echo "Error: Unknown parameter found: $1" |
| exit 1; |
| done |
| |
| if [[ $nocolor -eq 1 ]]; then |
| RESET='' |
| RED='' |
| GREEN='' |
| YELLOW='' |
| fi; |
| |
| if [[ -z "$outputfolder" ]]; then |
| outputfolder="./target" |
| fi |
| mkdir -p "$outputfolder" |
| |
| if [[ $dateoutput -eq 1 ]]; then |
| LOG_DATE="$(date +'%Y%m%d_%H%M%S')" |
| LOG_BASE="$outputfolder/baseVersionOutput_$LOG_DATE.csv" |
| LOG_CURRENT="$outputfolder/currentVersionOutput_$LOG_DATE.csv" |
| LOG_RESULT="$outputfolder/comparisonResult_$LOG_DATE.csv" |
| LOG_COMPARISON="$outputfolder/comparisonReport_$LOG_DATE.csv" |
| else |
| LOG_BASE="$outputfolder/baseVersionOutput.csv" |
| LOG_CURRENT="$outputfolder/currentVersionOutput.csv" |
| LOG_RESULT="$outputfolder/comparisonResult.csv" |
| LOG_COMPARISON="$outputfolder/comparisonReport.csv" |
| fi; |
| |
| # Check if both versions are set (required arguments) |
| if [[ -z $baseversion ]]; then |
| echo "Error: Base version not specified." |
| exit 1 |
| fi; |
| if [[ -z $currentversion ]]; then |
| echo "Error: Current version not specified." |
| exit 1 |
| fi; |
| |
| # Check if baseout is set, otherwise the benchmarks should be executed for base version |
| if [[ -n $baseoutput ]]; then |
| echo "Reading output file $baseoutput for base version." |
| |
| if [[ ! -f $baseoutput ]]; then |
| echo "Error: Output file $baseoutput cannot be read." |
| exit 1; |
| fi; |
| else |
| basemvnpath="$outputfolder/jackrabbit-oak-jackrabbit-oak-$baseversion/oak-benchmarks" |
| if [[ -z $basepath ]]; then |
| if [[ -n $basesource ]]; then |
| echo "Using sources in $basesource for base oak-benchmarks" |
| basemvnpath="$basesource" |
| else |
| echo "Path to base version not specified. Downloading sources... ${repositoryurl/version/$baseversion}" |
| wget -O "$outputfolder/jackrabbit-oak-$baseversion.tar.gz" "${repositoryurl/version/$baseversion}" -nv |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Base version couldn't be downloaded." |
| exit 1 |
| fi; |
| |
| echo "Unpacking sources..." |
| tar xf "$$outputfolder/jackrabbit-oak-$baseversion.tar.gz" -C "$outputfolder" |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Sources couldn't be unpacked." |
| exit 1 |
| fi; |
| fi; |
| |
| echo "Building oak-benchmarks in $basemvnpath" |
| mvn -B -f "$basemvnpath" install |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Maven failed building the project." |
| exit 1 |
| fi; |
| basepath="$basemvnpath/target/oak-benchmarks-$baseversion.jar" |
| fi; |
| |
| if [[ ! -f "./$basepath" ]]; then |
| echo "Error: Path to base version $basepath is not found." |
| exit 1 |
| fi; |
| fi; |
| |
| # Check if baseout is set, otherwise the benchmarks should be executed for current version |
| if [[ -n $currentoutput ]]; then |
| echo "Reading output file $currentoutput for current version." |
| |
| if [[ ! -f $currentoutput ]]; then |
| echo "Error: Output file $currentoutput cannot be read." |
| exit 1; |
| fi; |
| else |
| currentmvnpath="jackrabbit-oak-jackrabbit-oak-$currentversion/oak-benchmarks" |
| if [[ -z $currentpath ]]; then |
| if [[ -n $currentsource ]]; then |
| echo "Using sources in $currentsource for current oak-benchmarks" |
| currentmvnpath="$currentsource" |
| else |
| echo "Path to current version not specified. Downloading sources... ${repositoryurl/version/$currentversion}" |
| wget -O "jackrabbit-oak-$currentversion.tar.gz" "${repositoryurl/version/$currentversion}" -nv |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Current version couldn't be downloaded." |
| exit 1 |
| fi; |
| |
| echo "Unpacking sources..." |
| tar xf "jackrabbit-oak-$currentversion.tar.gz" |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Sources couldn't be unpacked." |
| exit 1 |
| fi; |
| fi; |
| |
| echo "Building oak-benchmarks in $currentmvnpath" |
| mvn -B -f "$currentmvnpath" install |
| if [[ $? -ne 0 ]]; then |
| echo "Error: Maven failed building the project." |
| exit 1 |
| fi; |
| currentpath="$currentmvnpath/target/oak-benchmarks-$currentversion.jar" |
| fi; |
| |
| if [[ ! -f "./$currentpath" ]]; then |
| echo "Error: Path to current version $currentpath is not found." |
| exit 1 |
| fi; |
| fi; |
| |
| if [[ -z $benchmarks ]]; then |
| benchmarks="$BENCHMARKS" |
| fi; |
| if [[ -z $fixtures ]]; then |
| fixtures="$FIXTURES" |
| fi; |
| |
| # Running benchmarks for base version in case $baseoutput is not set |
| if [[ -z $baseoutput ]]; then |
| echo "-----------------------------------------------------------" |
| echo "Executing benchmarks for version $baseversion" |
| echo "-----------------------------------------------------------" |
| baseoutput="$LOG_BASE" |
| for benchmark in $benchmarks |
| do |
| for fixture in $fixtures |
| do |
| rm -rf "jackrabbit-oak-jackrabbit-oak-$baseversion/oak-benchmarks/target/Jackrabbit-*" "jackrabbit-oak-jackrabbit-oak-$baseversion/oak-benchmarks/target/Oak-Tar-*" |
| cmd="java -Xmx2048m -jar $basepath benchmark --csvFile $LOG_BASE --cache 256 $extraargs $benchmark $fixture" |
| echo $cmd |
| $cmd |
| done |
| done |
| echo "-----------------------------------------" |
| echo "Benchmark completed. see $LOG_BASE for details:" |
| cat $LOG_BASE |
| fi; |
| |
| # Running benchmarks for current version in case $currentoutput is not set |
| if [[ -z $currentoutput ]]; then |
| echo "-----------------------------------------------------------" |
| echo "Executing benchmarks for version $currentversion" |
| echo "-----------------------------------------------------------" |
| currentoutput="$LOG_CURRENT" |
| for benchmark in $benchmarks |
| do |
| for fixture in $fixtures |
| do |
| rm -rf "jackrabbit-oak-jackrabbit-oak-$currentversion/oak-benchmarks/target/Jackrabbit-*" "jackrabbit-oak-jackrabbit-oak-$currentversion/oak-benchmarks/target/Oak-Tar-*" |
| cmd="java -Xmx2048m -jar $currentpath benchmark --csvFile $LOG_CURRENT --cache 256 $extraargs $benchmark $fixture" |
| echo $cmd |
| $cmd |
| done |
| done |
| echo "-----------------------------------------------------------" |
| echo "Benchmarks completed. see $LOG_CURRENT for details:" |
| cat $LOG_CURRENT |
| fi; |
| |
| IFS=, |
| |
| echo '' |
| echo "-----------------------------------------------------------" |
| echo "Comparing results of $currentversion against $baseversion" |
| echo "-----------------------------------------------------------" |
| while read test c min r10 r50 r90 max n; do |
| # Skip line if starts with # |
| if [[ ${test:0:1} == "#" ]]; then |
| Btest+=(${test:2}) |
| continue |
| fi; |
| Bc+=($c) |
| Bmin+=($min) |
| B10+=($r10) |
| B50+=($r50) |
| B90+=("${r90// /}") # Remove all spaces |
| Bmax+=($max) |
| Bn+=($n) |
| done < $baseoutput |
| |
| while read test c min r10 r50 r90 max n; do |
| # Skip line if starts with # |
| if [[ ${test:0:1} == "#" ]]; then |
| Ctest+=(${test:2}) |
| continue |
| fi; |
| Cc+=($c) |
| Cmin+=($min) |
| C10+=($r10) |
| C50+=($r50) |
| C90+=("${r90// /}") # Remove all spaces |
| Cmax+=($max) |
| Cn+=($n) |
| done < $currentoutput |
| |
| if [[ ${#Btest[@]} -ge ${#Ctest[@]} ]]; then |
| elements=${#Ctest[@]} |
| else |
| elements=${#Btest[@]} |
| fi; |
| |
| # Loop through results calculating the difference ratio |
| total=0 |
| max=0 |
| min=1000 |
| skipped=0 |
| |
| echo '' |
| echo 'Average time to run Benchmarks for current and base versions. Lower value is better:' |
| echo '----------------------------------------------------------------------------------------------' |
| printf "| %-30s | %-14s | %-14s | %-10s | %-10s |\n" 'TEST NAME' 'BASE (ms)' 'CURRENT (ms)' 'RATIO' 'PERCENTAGE' |
| printf "%-30s, %-14s, %-14s, %-10s, %-10s\n" 'TEST NAME' 'BASE (ms)' 'CURRENT (ms)' 'RATIO' 'PERCENTAGE' >> $LOG_COMPARISON |
| echo '----------------------------------------------------------------------------------------------' |
| for ((i=0;i<=elements-1;i++)); do |
| basetest=${Btest[$i]} |
| currenttest=${Ctest[$i]} |
| |
| if [[ "$basetest" != "$currenttest" ]]; then |
| skipped=$skipped+1 |
| continue |
| fi; |
| |
| basevalue=${B90[$i]} |
| currentvalue=${C90[$i]} |
| ratio=$(echo "scale=4 ; $currentvalue / $basevalue" | bc) |
| if (( $(echo "$ratio > $max" |bc -l) )); then |
| max=$ratio |
| fi; |
| if (( $(echo "$ratio < $min" |bc -l) )); then |
| min=$ratio |
| fi; |
| total=$(echo "scale=4 ; $total + $ratio" | bc) |
| percentage=$(echo "scale=2 ; ($ratio * 100 - 100) /1" | bc) |
| if (( $(echo "$percentage > 0" |bc) )); then |
| printf "${RESET}| %-30s | %-14s | %-14s | ${RED}%-10s ${RESET}| ${RED}%-10s ${RESET}| \n" $basetest $basevalue $currentvalue $ratio $percentage |
| elif (( $(echo "$percentage < 0" |bc) )); then |
| printf "${RESET}| %-30s | %-14s | %-14s | ${GREEN}%-10s ${RESET}| ${GREEN}%-10s ${RESET}| \n" $basetest $basevalue $currentvalue $ratio $percentage |
| else |
| printf "${RESET}| %-30s | %-14s | %-14s | %-10s ${RESET}| %-10s ${RESET}| \n" $basetest $basevalue $currentvalue $ratio $percentage |
| fi; |
| printf '%-30s, %-14s, %-14s, %-10s, %-10s\n' $basetest $basevalue $currentvalue $ratio $percentage >> $LOG_COMPARISON |
| done |
| echo '----------------------------------------------------------------------------------------------' |
| |
| if [[ $skipped -gt 0 ]]; then |
| echo -e "${YELLOW}Skipped $skipped tests because order doesn't match${RESET}\n" |
| fi; |
| |
| echo "" |
| echo "Performance difference between versions:" |
| average=$(echo "scale=4 ; $total / $elements" | bc) |
| |
| # Show the average, maximum and minimum ratio |
| echo '----------------------------------------------------' |
| printf "| %-14s | %-14s | %-14s |\n" 'AVERAGE' 'MAXIMUM' 'MINIMUM' |
| echo '----------------------------------------------------' |
| printf "| %-14s | %-14s | %-14s |\n" $average $max $min |
| echo '----------------------------------------------------' |
| |
| printf "%-14s, %-14s, %-14s\n" 'AVERAGE' 'MAXIMUM' 'MINIMUM' >> $LOG_RESULT |
| printf "%-14s, %-14s, %-14s\n" $average $max $min >> $LOG_RESULT |
| |
| echo "Results have been saved to file $LOG_RESULT" |