153a5a1b3Sopenharmony_ci#!/bin/bash
253a5a1b3Sopenharmony_ci
353a5a1b3Sopenharmony_ci# This file is part of PulseAudio.
453a5a1b3Sopenharmony_ci#
553a5a1b3Sopenharmony_ci# Copyright 2015 Ahmed S. Darwish <darwish.07@gmail.com>
653a5a1b3Sopenharmony_ci#
753a5a1b3Sopenharmony_ci# PulseAudio is free software; you can redistribute it and/or modify
853a5a1b3Sopenharmony_ci# it under the terms of the GNU Lesser General Public License as published by
953a5a1b3Sopenharmony_ci# the Free Software Foundation; either version 2 of the License, or
1053a5a1b3Sopenharmony_ci# (at your option) any later version.
1153a5a1b3Sopenharmony_ci#
1253a5a1b3Sopenharmony_ci# PulseAudio is distributed in the hope that it will be useful, but
1353a5a1b3Sopenharmony_ci# WITHOUT ANY WARRANTY; without even the implied warranty of
1453a5a1b3Sopenharmony_ci# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1553a5a1b3Sopenharmony_ci# General Public License for more details.
1653a5a1b3Sopenharmony_ci#
1753a5a1b3Sopenharmony_ci# You should have received a copy of the GNU Lesser General Public License
1853a5a1b3Sopenharmony_ci# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1953a5a1b3Sopenharmony_ci
2053a5a1b3Sopenharmony_ci#
2153a5a1b3Sopenharmony_ci# Measure PulseAudio memory usage (VmSize, Private+Shared_Dirty)
2253a5a1b3Sopenharmony_ci# while increasing the number of connected clients over time.
2353a5a1b3Sopenharmony_ci#
2453a5a1b3Sopenharmony_ci# To avoid premature client exits, please ensure giving a long
2553a5a1b3Sopenharmony_ci# wave file as the script's first parameter.
2653a5a1b3Sopenharmony_ci#
2753a5a1b3Sopenharmony_ci
2853a5a1b3Sopenharmony_ci_bold="\x1B[1m"
2953a5a1b3Sopenharmony_ci_error="\x1B[1;31m"
3053a5a1b3Sopenharmony_ci_reset="\x1B[0m"
3153a5a1b3Sopenharmony_ci
3253a5a1b3Sopenharmony_ciBASENAME=$(basename $0)
3353a5a1b3Sopenharmony_ciPROMPT="${_bold}[$BASENAME]${_reset}"
3453a5a1b3Sopenharmony_cierror() {
3553a5a1b3Sopenharmony_ci    echo -e "$PROMPT: ** Error: ${_error}$1${_reset}" >&2; exit -1
3653a5a1b3Sopenharmony_ci}
3753a5a1b3Sopenharmony_cimsg() {
3853a5a1b3Sopenharmony_ci    echo -e "$PROMPT: $1"
3953a5a1b3Sopenharmony_ci}
4053a5a1b3Sopenharmony_ci
4153a5a1b3Sopenharmony_ci_absolute_dirname="$(dirname `readlink -f $0`)"
4253a5a1b3Sopenharmony_ciPA_HOME="${_absolute_dirname%/scripts}"
4353a5a1b3Sopenharmony_ci[ -d "$PA_HOME/src" -a -d "$PA_HOME/scripts" ] ||
4453a5a1b3Sopenharmony_ci    error "This script can only be executed from PulseAudio source tree"
4553a5a1b3Sopenharmony_ci
4653a5a1b3Sopenharmony_ciPA=${PA_HOME}/src/pulseaudio
4753a5a1b3Sopenharmony_ciPA_CAT=${PA_HOME}/src/pacat
4853a5a1b3Sopenharmony_ciPA_PLAY=${PA_HOME}/src/paplay
4953a5a1b3Sopenharmony_ciPA_FLAGS="-n -F ${PA_HOME}/src/default.pa -p ${PA_HOME}/src/"
5053a5a1b3Sopenharmony_ci
5153a5a1b3Sopenharmony_ci[ -L "$PA_PLAY" ] || ln -sf .libs/lt-pacat $PA_PLAY
5253a5a1b3Sopenharmony_ciPA_PLAY_PROCESS_NAME="paplay"
5353a5a1b3Sopenharmony_ci
5453a5a1b3Sopenharmony_ciSCRIPTS_DIR=${PA_HOME}/scripts
5553a5a1b3Sopenharmony_ciBENCHMARKS_DIR=${SCRIPTS_DIR}/benchmarks
5653a5a1b3Sopenharmony_ciGNUPLOT_SCRIPT=${SCRIPTS_DIR}/plot_memory_usage.gp
5753a5a1b3Sopenharmony_ciOUTPUT_FILE=${BENCHMARKS_DIR}/memory-usage-`date -Iseconds`.txt
5853a5a1b3Sopenharmony_ciSYMLINK_LATEST_OUTPUT_FILE=${BENCHMARKS_DIR}/memory-usage-LATEST.txt
5953a5a1b3Sopenharmony_ci
6053a5a1b3Sopenharmony_ciMAX_CLIENTS=30
6153a5a1b3Sopenharmony_ci
6253a5a1b3Sopenharmony_ci[ -e "$PA" ] || error "$PA does not exist. Compile PulseAudio tree first."
6353a5a1b3Sopenharmony_ci[ -x "$PA" ] || error "$PA cannot be executed"
6453a5a1b3Sopenharmony_ci[ -x "$PA_CAT" ] || error "$PA_CAT cannot be executed"
6553a5a1b3Sopenharmony_ci
6653a5a1b3Sopenharmony_ciAUDIO_FILE="$1"
6753a5a1b3Sopenharmony_ci[ -n "$AUDIO_FILE" ] || error "Usage: $BASENAME AUDIO_FILE"
6853a5a1b3Sopenharmony_ci[ -e "$AUDIO_FILE" ] || error "$AUDIO_FILE does not exist"
6953a5a1b3Sopenharmony_ci[ -f "$AUDIO_FILE" ] || error "$AUDIO_FILE is not a regular file"
7053a5a1b3Sopenharmony_ci
7153a5a1b3Sopenharmony_ci$PA --check >/dev/null 2>&1
7253a5a1b3Sopenharmony_ci[ "$?" -ne "0" ] || {
7353a5a1b3Sopenharmony_ci    msg "A PulseAudio daemon is already running on your system"
7453a5a1b3Sopenharmony_ci    msg "To use this script, please do the following first:"
7553a5a1b3Sopenharmony_ci    msg " 1. Add autospawn=no to $HOME/.pulse/client.conf"
7653a5a1b3Sopenharmony_ci    msg " 2. Kill current daemon instance using 'pulseaudio --kill'"
7753a5a1b3Sopenharmony_ci    error "Failed to start PulseAudio daemon"
7853a5a1b3Sopenharmony_ci}
7953a5a1b3Sopenharmony_ci
8053a5a1b3Sopenharmony_cimsg "Hello. Benchmarking PulseAudio daemon memory usage over time"
8153a5a1b3Sopenharmony_ci
8253a5a1b3Sopenharmony_ci# Check Linux Kernel's Documentation/sysctl/vm.txt for details.
8353a5a1b3Sopenharmony_cimsg "Ensuring consistent results by dropping all VM caches!"
8453a5a1b3Sopenharmony_cisudo bash -c "sync && echo 3 >/proc/sys/vm/drop_caches"
8553a5a1b3Sopenharmony_ci
8653a5a1b3Sopenharmony_cimsg "Starting PulseAudio daemon"
8753a5a1b3Sopenharmony_ciPULSE_LOG=0 PULSE_LOG_COLORS= PULSE_LOG_META= $PA $PA_FLAGS &
8853a5a1b3Sopenharmony_ci_pid=$!
8953a5a1b3Sopenharmony_ci
9053a5a1b3Sopenharmony_ci# Give PA daemon time to initialize everything and vacuum. We want
9153a5a1b3Sopenharmony_ci# to make the _starting_ dirty RSS memory usage (0 clients) as
9253a5a1b3Sopenharmony_ci# equivalent as possible for multiple trials.
9353a5a1b3Sopenharmony_cisleep 12
9453a5a1b3Sopenharmony_ci
9553a5a1b3Sopenharmony_ci$PA --check >/dev/null 2>&1
9653a5a1b3Sopenharmony_ci[ "$?" -eq "0" ] || error "Failed to start PulseAudio daemon"
9753a5a1b3Sopenharmony_ci
9853a5a1b3Sopenharmony_ciecho "# ClientCount    VmSize (KiB)     DirtyRSS (KiB)" >$OUTPUT_FILE
9953a5a1b3Sopenharmony_ci
10053a5a1b3Sopenharmony_cimsg "Starting PulseAudio clients"
10153a5a1b3Sopenharmony_ci_i=1;
10253a5a1b3Sopenharmony_ciwhile true; do
10353a5a1b3Sopenharmony_ci    [ "$_i" -le "$MAX_CLIENTS" ] || break
10453a5a1b3Sopenharmony_ci
10553a5a1b3Sopenharmony_ci    _vmsize=`ps -o vsize= $_pid`
10653a5a1b3Sopenharmony_ci    _drss=`awk '/(Shared|Private)_Dirty:/{ sum += $2 } END { print sum }' /proc/$_pid/smaps`
10753a5a1b3Sopenharmony_ci    [ "$?" -eq "0" ] || error "Error sampling PulseAudio RSS memory usage"
10853a5a1b3Sopenharmony_ci
10953a5a1b3Sopenharmony_ci    echo "  $_i              $_vmsize           $_drss" >>$OUTPUT_FILE
11053a5a1b3Sopenharmony_ci
11153a5a1b3Sopenharmony_ci    $PA_PLAY $AUDIO_FILE 2>/dev/null &
11253a5a1b3Sopenharmony_ci    _i=$((_i + 1))
11353a5a1b3Sopenharmony_ci
11453a5a1b3Sopenharmony_ci    sleep 1
11553a5a1b3Sopenharmony_cidone
11653a5a1b3Sopenharmony_cimsg "Finished starting ${MAX_CLIENTS} PulseAudio clients over time"
11753a5a1b3Sopenharmony_ci
11853a5a1b3Sopenharmony_ci_n_clients_still_alive=$(ps -C $PA_PLAY_PROCESS_NAME --no-headers | wc -l)
11953a5a1b3Sopenharmony_ci[ "$_n_clients_still_alive" -ge "$MAX_CLIENTS" ] || {
12053a5a1b3Sopenharmony_ci    msg "You did not provide a long-enough wave file for clients to play"
12153a5a1b3Sopenharmony_ci    msg "Only $_n_clients_still_alive clients are now active; expected $MAX_CLIENTS"
12253a5a1b3Sopenharmony_ci    error "Please provide a large wave file (~ $((MAX_CLIENTS*2))s) then redo the benchmarks"
12353a5a1b3Sopenharmony_ci}
12453a5a1b3Sopenharmony_ci
12553a5a1b3Sopenharmony_cimsg "Killing PulseAudio daemon"
12653a5a1b3Sopenharmony_ci$PA --kill >/dev/null 2>&1
12753a5a1b3Sopenharmony_ci
12853a5a1b3Sopenharmony_cirm -f $SYMLINK_LATEST_OUTPUT_FILE
12953a5a1b3Sopenharmony_ciln -s $OUTPUT_FILE $SYMLINK_LATEST_OUTPUT_FILE
13053a5a1b3Sopenharmony_ci
13153a5a1b3Sopenharmony_cimsg "Sampling daemon memory usage done!"
13253a5a1b3Sopenharmony_cimsg "Check the results at $SYMLINK_LATEST_OUTPUT_FILE"
13353a5a1b3Sopenharmony_cimsg "Plot these results using 'gnuplot $GNUPLOT_SCRIPT'"
134