Reduce VOIP audio stuttering by increasing deamon priority
On occassion our FreeSWITCH Linode VPS stutter which I believe is because the server overall gets a little busy with everything else that is installed. One noticeable way tp reduce or almost eliminate this is to run the FreeSWITCH VOIP daemon in real time priority. But before I begin please do +1 or share if it helps you as it helps me.
On Ubuntu/Debian chaning FreeSWITCH priority is easily accomplished by modifying the `/etc/init.d/freeswitch` start-up script and adding the `rc` real time execute options to the `DAEMON_ARGS` argument – but if you want set the priority even higher scroll to bottom of post.
An example of a FreeSWITCH init.d script can be found on the FreeSWITCH Wiki page which - I think is more complete then the sample included in the source files.
#!/bin/bash ### BEGIN INIT INFO # Provides: freeswitch # Required-Start: $local_fs $remote_fs $network # Required-Stop: $local_fs $remote_fs $network # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Description: FreeSWITCH debian init script. # Author: Matthew Williams # ### END INIT INFO # Do NOT "set -e" # PATH should only include /usr/* if it runs after the mountnfs.sh script PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin DESC="Freeswitch" NAME=freeswitch DAEMON=/usr/local/freeswitch/bin/$NAME DAEMON_ARGS="-nc -np" # -rp is for real-time priority, -np for normal system priority PIDFILE=/usr/local/freeswitch/run/$NAME.pid SCRIPTNAME=/etc/init.d/$NAME FS_USER=freeswitch FS_GROUP=daemon # Exit if the package is not installed [ -x "$DAEMON" ] || exit 0 # Read configuration variable file if it is present [ -r /etc/default/$NAME ] && . /etc/default/$NAME # Load the VERBOSE setting and other rcS variables . /lib/init/vars.sh # Define LSB log_* functions. # Depend on lsb-base (>= 3.0-6) to ensure that this file is present. . /lib/lsb/init-functions # # Function that sets ulimit values for the daemon # do_setlimits() { ulimit -c unlimited ulimit -d unlimited ulimit -f unlimited ulimit -i unlimited ulimit -n 999999 ulimit -q unlimited ulimit -u unlimited ulimit -v unlimited ulimit -x unlimited ulimit -s 240 ulimit -l unlimited return 0 } # # Function that starts the daemon/service # do_start() { # Set user to run as if [ $FS_USER ] ; then DAEMON_ARGS="`echo $DAEMON_ARGS` -u $FS_USER" fi # Set group to run as if [ $FS_GROUP ] ; then DAEMON_ARGS="`echo $DAEMON_ARGS` -g $FS_GROUP" fi # Return # 0 if daemon has been started # 1 if daemon was already running # 2 if daemon could not be started start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null -- \ || return 1 do_setlimits start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 # Add code here, if necessary, that waits for the process to be ready # to handle requests from services started subsequently which depend # on this one. As a last resort, sleep for some time. } # # Function that stops the daemon/service # do_stop() { # Return # 0 if daemon has been stopped # 1 if daemon was already stopped # 2 if daemon could not be stopped # other if a failure occurred start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 --pidfile $PIDFILE --name $NAME RETVAL="$?" [ "$RETVAL" = 2 ] && return 2 # Wait for children to finish too if this is a daemon that forks # and if the daemon is only ever run from this initscript. # If the above conditions are not satisfied then add some other code # that waits for the process to drop all resources that could be # needed by services started subsequently. A last resort is to # sleep for some time. start-stop-daemon --stop --quiet --oknodo --retry=0/30/KILL/5 --exec $DAEMON [ "$?" = 2 ] && return 2 # Many daemons don't delete their pidfiles when they exit. rm -f $PIDFILE return "$RETVAL" } # # Function that sends a SIGHUP to the daemon/service # do_reload() { # # If the daemon can reload its configuration without # restarting (for example, when it is sent a SIGHUP), # then implement that here. # start-stop-daemon --stop --signal 1 --quiet --pidfile $PIDFILE --name $NAME return 0 } case "$1" in start) [ "$VERBOSE" != no ] && log_daemon_msg "Starting $DESC" "$NAME" do_start case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; stop) [ "$VERBOSE" != no ] && log_daemon_msg "Stopping $DESC" "$NAME" do_stop case "$?" in 0|1) [ "$VERBOSE" != no ] && log_end_msg 0 ;; 2) [ "$VERBOSE" != no ] && log_end_msg 1 ;; esac ;; #reload|force-reload) # # If do_reload() is not implemented then leave this commented out # and leave 'force-reload' as an alias for 'restart'. # #log_daemon_msg "Reloading $DESC" "$NAME" #do_reload #log_end_msg $? #;; restart|force-reload) # # If the "reload" option is implemented then remove the # 'force-reload' alias # log_daemon_msg "Restarting $DESC" "$NAME" do_stop case "$?" in 0|1) do_start case "$?" in 0) log_end_msg 0 ;; 1) log_end_msg 1 ;; # Old process is still running *) log_end_msg 1 ;; # Failed to start esac ;; *) # Failed to stop log_end_msg 1 ;; esac ;; *) #echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2 echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2 exit 3 ;; esac
Setting the deamon priority even higher
To set the priority even higher you used to be able to pass the system default priority `np` option to FreeSWITCH executable and then the desired nice level directly to the `start-stop-deamon` but as of Jan 2013 '-np' option defaults to priority 19.
Use the below work around which changes the priority after freeswitch starts up.
#!/bin/bash ### BEGIN INIT INFO ... DAEMON_ARGS="-nc -rp" # -rp is for real-time priority, -np for normal system priority, -lp for low priority ... sstart-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null -- \ || return 1 do_setlimits start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON -- \ $DAEMON_ARGS \ || return 2 ... # increase priority further, using -20 is not recommended sleep 15 # wait for all children to start renice -n -19 -u freeswitch
Use UDP Transport instead of TCP
The last tweak that might help is using UDP. This transport protocol has less overhead as for one it does not require packet acknowledgement. Check your client and confirm the UDP is selected; speaking of VOIP clients I recommend open source Linphone - a multi line and multi OS (Android, Windows, Linux, etc) client; the latest snapshot builds work the best in my experience.
FreeSWITCH Command Line Options
For a list of all available FreeSWITCH command options see this Command Line wiki page.
I'm running into this right now... I set it to -rp,but the IVR still stutters a bit. I'm going try caching media files that are used by referencing the link below.
ReplyDeletehttp://wiki.freeswitch.org/wiki/Mod_http_cache
Try the bit in "Setting the deamon priority even higher" section.
DeleteThis comment has been removed by the author.
ReplyDelete