1#!/bin/bash 2 3# This file is part of PulseAudio. 4# 5# Copyright 2015 Ahmed S. Darwish <darwish.07@gmail.com> 6# 7# PulseAudio is free software; you can redistribute it and/or modify 8# it under the terms of the GNU Lesser General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# PulseAudio is distributed in the hope that it will be useful, but 13# WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15# General Public License for more details. 16# 17# You should have received a copy of the GNU Lesser General Public License 18# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 19 20# 21# Measure PulseAudio memory usage (VmSize, Private+Shared_Dirty) 22# while increasing the number of connected clients over time. 23# 24# To avoid premature client exits, please ensure giving a long 25# wave file as the script's first parameter. 26# 27 28_bold="\x1B[1m" 29_error="\x1B[1;31m" 30_reset="\x1B[0m" 31 32BASENAME=$(basename $0) 33PROMPT="${_bold}[$BASENAME]${_reset}" 34error() { 35 echo -e "$PROMPT: ** Error: ${_error}$1${_reset}" >&2; exit -1 36} 37msg() { 38 echo -e "$PROMPT: $1" 39} 40 41_absolute_dirname="$(dirname `readlink -f $0`)" 42PA_HOME="${_absolute_dirname%/scripts}" 43[ -d "$PA_HOME/src" -a -d "$PA_HOME/scripts" ] || 44 error "This script can only be executed from PulseAudio source tree" 45 46PA=${PA_HOME}/src/pulseaudio 47PA_CAT=${PA_HOME}/src/pacat 48PA_PLAY=${PA_HOME}/src/paplay 49PA_FLAGS="-n -F ${PA_HOME}/src/default.pa -p ${PA_HOME}/src/" 50 51[ -L "$PA_PLAY" ] || ln -sf .libs/lt-pacat $PA_PLAY 52PA_PLAY_PROCESS_NAME="paplay" 53 54SCRIPTS_DIR=${PA_HOME}/scripts 55BENCHMARKS_DIR=${SCRIPTS_DIR}/benchmarks 56GNUPLOT_SCRIPT=${SCRIPTS_DIR}/plot_memory_usage.gp 57OUTPUT_FILE=${BENCHMARKS_DIR}/memory-usage-`date -Iseconds`.txt 58SYMLINK_LATEST_OUTPUT_FILE=${BENCHMARKS_DIR}/memory-usage-LATEST.txt 59 60MAX_CLIENTS=30 61 62[ -e "$PA" ] || error "$PA does not exist. Compile PulseAudio tree first." 63[ -x "$PA" ] || error "$PA cannot be executed" 64[ -x "$PA_CAT" ] || error "$PA_CAT cannot be executed" 65 66AUDIO_FILE="$1" 67[ -n "$AUDIO_FILE" ] || error "Usage: $BASENAME AUDIO_FILE" 68[ -e "$AUDIO_FILE" ] || error "$AUDIO_FILE does not exist" 69[ -f "$AUDIO_FILE" ] || error "$AUDIO_FILE is not a regular file" 70 71$PA --check >/dev/null 2>&1 72[ "$?" -ne "0" ] || { 73 msg "A PulseAudio daemon is already running on your system" 74 msg "To use this script, please do the following first:" 75 msg " 1. Add autospawn=no to $HOME/.pulse/client.conf" 76 msg " 2. Kill current daemon instance using 'pulseaudio --kill'" 77 error "Failed to start PulseAudio daemon" 78} 79 80msg "Hello. Benchmarking PulseAudio daemon memory usage over time" 81 82# Check Linux Kernel's Documentation/sysctl/vm.txt for details. 83msg "Ensuring consistent results by dropping all VM caches!" 84sudo bash -c "sync && echo 3 >/proc/sys/vm/drop_caches" 85 86msg "Starting PulseAudio daemon" 87PULSE_LOG=0 PULSE_LOG_COLORS= PULSE_LOG_META= $PA $PA_FLAGS & 88_pid=$! 89 90# Give PA daemon time to initialize everything and vacuum. We want 91# to make the _starting_ dirty RSS memory usage (0 clients) as 92# equivalent as possible for multiple trials. 93sleep 12 94 95$PA --check >/dev/null 2>&1 96[ "$?" -eq "0" ] || error "Failed to start PulseAudio daemon" 97 98echo "# ClientCount VmSize (KiB) DirtyRSS (KiB)" >$OUTPUT_FILE 99 100msg "Starting PulseAudio clients" 101_i=1; 102while true; do 103 [ "$_i" -le "$MAX_CLIENTS" ] || break 104 105 _vmsize=`ps -o vsize= $_pid` 106 _drss=`awk '/(Shared|Private)_Dirty:/{ sum += $2 } END { print sum }' /proc/$_pid/smaps` 107 [ "$?" -eq "0" ] || error "Error sampling PulseAudio RSS memory usage" 108 109 echo " $_i $_vmsize $_drss" >>$OUTPUT_FILE 110 111 $PA_PLAY $AUDIO_FILE 2>/dev/null & 112 _i=$((_i + 1)) 113 114 sleep 1 115done 116msg "Finished starting ${MAX_CLIENTS} PulseAudio clients over time" 117 118_n_clients_still_alive=$(ps -C $PA_PLAY_PROCESS_NAME --no-headers | wc -l) 119[ "$_n_clients_still_alive" -ge "$MAX_CLIENTS" ] || { 120 msg "You did not provide a long-enough wave file for clients to play" 121 msg "Only $_n_clients_still_alive clients are now active; expected $MAX_CLIENTS" 122 error "Please provide a large wave file (~ $((MAX_CLIENTS*2))s) then redo the benchmarks" 123} 124 125msg "Killing PulseAudio daemon" 126$PA --kill >/dev/null 2>&1 127 128rm -f $SYMLINK_LATEST_OUTPUT_FILE 129ln -s $OUTPUT_FILE $SYMLINK_LATEST_OUTPUT_FILE 130 131msg "Sampling daemon memory usage done!" 132msg "Check the results at $SYMLINK_LATEST_OUTPUT_FILE" 133msg "Plot these results using 'gnuplot $GNUPLOT_SCRIPT'" 134