1#!/bin/bash -eu 2# Copyright 2025 The OpenSSL Project Authors. All Rights Reserved. 3# 4# Licensed under the Apache License 2.0 (the "License"). 5# You may not use this file except in compliance with the License. 6# You can obtain a copy in the file LICENSE in the source distribution 7# or at https://www.openssl.org/source/license.html 8# 9# Script to analyze logs produced by REPORT_RWLOCK_CONTENTION 10# Usage: ./analyze-contention-log.sh <logfile> 11################################################################### 12 13# 14# Setup a temp directory to massage our log file 15# 16TEMPDIR=$(mktemp -d /tmp/contention.XXXXXX) 17 18trap "rm -rf $TEMPDIR" EXIT 19 20echo "Splitting files" > /dev/stderr 21 22# 23#start by splitting the log into separate stack traces 24# 25mkdir "$TEMPDIR/individual_files" 26cat "$@" > "$TEMPDIR/individual_files/log" 27pushd $TEMPDIR/individual_files/ > /dev/null 28awk ' 29 BEGIN {RS = ""; FS = "\n"} 30 {file_num++; print > ("stacktrace" file_num ".txt")}' ./log 31popd > /dev/null 32rm -f $TEMPDIR/individual_files/log 33 34# 35# Make some associative arrays to track our stats 36# 37declare -A filenames 38declare -A total_latency 39declare -A latency_counts 40 41echo "Gathering latencies" > /dev/stderr 42FILECOUNT=$(ls $TEMPDIR/individual_files/stacktrace*.* | wc -l) 43currentidx=0 44 45# 46# Look at every stack trace, get and record its latency, and hash value 47# 48for i in $(ls $TEMPDIR/individual_files/stacktrace*.*) 49do 50 LATENCY=$(awk '{print $6}' $i) 51 #drop the non-stacktrace line 52 sed -i -e"s/lock blocked on.*//" $i 53 #now compute its sha1sum 54 SHA1SUM=$(sha1sum $i | awk '{print $1}') 55 filenames["$SHA1SUM"]=$i 56 CUR_LATENCY=0 57 LATENCY_COUNT=0 58 59 # 60 # If we already have a latency total for this hash value 61 # fetch it from the total_latency array, along with 62 # the number of times we've encountered this hash 63 # 64 if [[ -v total_latency["$SHA1SUM"] ]] 65 then 66 CUR_LATENCY=${total_latency["$SHA1SUM"]} 67 LATENCY_COUNT=${latency_counts["$SHA1SUM"]} 68 fi 69 70 # 71 # Add this files latency to the hashes total latency amount 72 # and increment its associated count by 1 73 # 74 total_latency["$SHA1SUM"]=$(dc -e "$CUR_LATENCY $LATENCY + p") 75 latency_counts["$SHA1SUM"]=$(dc -e "$LATENCY_COUNT 1 + p") 76 echo -e -n "FILE $currentidx/$FILECOUNT \r" > /dev/stderr 77 currentidx=$((currentidx + 1)) 78done 79 80# 81# Write out each latency in the hash array to a file named after its total latency 82# 83mkdir $TEMPDIR/sorted_latencies/ 84for i in ${!total_latency[@]} 85do 86 TOTAL=${total_latency[$i]} 87 COUNT=${latency_counts[$i]} 88 FNAME=${filenames[$i]} 89 AVG=$(dc -e "6 k $TOTAL $COUNT / p") 90 echo "Total latency $TOTAL usec, count $COUNT (avg $AVG usec)" >> $TEMPDIR/sorted_latencies/$TOTAL.txt 91 cat $FNAME >> $TEMPDIR/sorted_latencies/$TOTAL.txt 92done 93 94# 95# Now because we have our cumulative latencies recorded in files named 96# after their total cumulative latency, we can easily do a numerical 97# sort on them in reverse order to display them from greatest to least 98# 99echo "Top latencies" 100for i in $(ls $TEMPDIR/sorted_latencies/ | sort -n -r) 101do 102 echo "=============================================" 103 cat $TEMPDIR/sorted_latencies/$i 104 echo "" 105done 106 107