Friday, January 19, 2018

RaspBerry Pi - The Audio Engine - Part 4 - Advanced OS Tuning Measures

Nice to have you back @ Part 4 of the series.

By now you already should have a nicely running audio system based on the Raspberry PI3, a nice little HAT DAC and piCorePlayer as audio engine.


This part of the "RPI Audio Engine series" will cover some more modifications.


As with all tuning measures the ultimate goal is to make the system more efficient and to get rid of distractions. 

Everything until now, including some basic tweaks (HDMI off/WLAN off etc.), could be accomplished by using the WEB GUI.

Now it's time to switch to commandline.  Some might don't like it. Some might be afraid 
of it. You might reconsider.

Keep in mind. You can't do much wrong. If so. Just restore your backed-up SD-card, if anything has gone south.

I'll try to walk you through the journey. Tweak by Tweak.

Still. Remember. Everything you do you do at your own risk! Just to be clear about that.


This article is still Work-in-Progress!  Latest update: Jan-24-2018




But before your start make a backup of your SD card first. If something gets messed up,
you can easily restore the status quo.


Let's get started.


1. ssh login

I won't get into that right now. There are numerous guides out there how to accomplish this from any platform.

You'll need the IP address. We covered that in Part 2
You'll need a user name. "tc"
You'll need a password.   "piCore"

Basically you'll end up like this:






Now we need to become user "root" to be able to execute administration tasks.  
And then we need to mount the boot-partition to be be able to edit some core config files.

Just type (or copy/paste):

####################################
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
sudo su


########################################





Let's backup the key files first - run this step only once:




Copy &  paste everything between the hashes. 

##########################
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}

test -f /mnt/mmcblk0p1/config.txt.orig || {
sudo cp /mnt/mmcblk0p1/config.txt /mnt/mmcblk0p1/config.txt.orig
sync
}
test -f /mnt/mmcblk0p1/cmdline.txt.orig || {
sudo cp /mnt/mmcblk0p1/cmdline.txt /mnt/mmcblk0p1/cmdline.txt.orig
sync
}

##########################

Now we're set to introduce this or that measure.


Measure 1  -- Turn Off Power and Act LEDs


There are two LEDs on the PI. These 

a. draw about 5mA current
b. might cause an annoying light spectacle in a dark listening room.
c. and cause certain activity on the CPU

Copy &  paste everything below after you've done a reboot and a ssh login again. 
Everything between hashes all at once!

###################################################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cat <<"EOF" >>/mnt/mmcblk0p1/config.txt
### Turn off LEDs
# Disable the ACT LED
dtparam=act_led_trigger=none
dtparam=act_led_activelow=on
# Disable the PWR LED
dtparam=pwr_led_trigger=none
dtparam=pwr_led_activelow=on 
EOF
sync
reboot

###################################################

Done. After a reboot the system LEDs should be off .

Great. You managed your first tweak.

To restore the original - just in case:


Copy &  paste below after you've done a reboot and a ssh login again. 

##############################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cp /mnt/mmcblk0p1/config.txt.orig /mnt/mmcblk0p1/config.txt
sync
reboot

##############################

That's about it.


Measure 2 -- Isolate Interrupts

Basically all interrupts run on CPU0. This is specific to the RPI. 
On a PC IRQs get distributed over several CPUs. On a PC you can even assign IRQs manually to a specific CPU. Not so on the PI.

Now. We do what's possible under these circumstances.

This measure will isolate all running SW processes
from CPU0. CPU0 will then handle IRQs exclusive!

On CPU0 there won't be any competition between IRQs and processes anymore.

As usual, ssh login first. 


Copy &  paste below after you've done a reboot and a ssh login again. 

################################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cd /mnt/mmcblk0p1
sed -i 's/$/ isolcpus=0,1/' cmdline.txt
sync
reboot

################################

To restore the original - just in case:


Copy &  paste below after you've done a reboot and a ssh login again. 

##############################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cp /mnt/mmcblk0p1/cmdline.txt.orig /mnt/mmcblk0p1/cmdline.txt
sync
reboot

##############################

That's about it.




Measure 3 -- Shutdown Webserver and cron

As usual, ssh login first.

piCorePlayer is a very lean system. Only a very few services/processes are running.
We can still lower the number of services, to increase the system efficiency. 

The Webserver is probably the most demanding service. Once everything is configured
there's pretty much no need to have that server running idle in the background.

Cron is a daemon that allows to run tasks at certain times.

With this measure we're using the service cron to shutdown the webserver after
3 minutes. And while we're at it, cron shuts down itself too.

3 minutes will also give you plenty of time to disable this measure from a browser again.

Now we have to generate a script that will do the job and that's been called by cron.


Copy &  paste below after you've done a reboot and a ssh login again. 

####################################
sudo su
cd /mnt/mmcblk0p2/tce
touch tune.sh
chmod 770 tune.sh
cat <<"EOF" >tune.sh
#!/bin/sh
#
#
###
test -f /tmp/tunep1 || { touch /tmp/tunep1 ; exit 0 ; } ;
pkill busybox-httpd

sleep 1
pkill crond
touch /tmp/tunep2

EOF
sync
reboot

#####################################


Now we can activate a cron job that calls the script that we just generated.
While running the script, it'll also kill the cron daemon! 

We'll do this from the WEB GUI inside the "Tweak" section.






Enter (copy/paste) above shown "Custom Cron Command" and press "Save". 

###############

*/3 * * * * /mnt/mmcblk0p2/tce/tune.sh

###############


3 minutes after a power-up or reboot the WEB-UI should no longer be working.

If you want to disable above measure, just remove the  "Custom Cron Command" string and save it within 3 minutes after boot.



Measure 4 -- Disable DHCP and ssh

Now. This measure builds upon Measure 3, which has to be done before this one! 

This exercise I wouldn't consider optional. Just to mention it.

There are basically just two remaining processes that we are able to spare. 
It's dhcp and ssh.

Obviously if we kill ssh - the remote login daemon - we won't be able to ssh login any more. You may consider to run this measure as the very final exercise. Or you disable
the cron job inside the "Schedule Cron Jobs" menu as described in Measure 3 first. 
And then you go ahead with this one.

Copy &  paste below after you've done a reboot and a ssh login again. 

####################################
sudo su
cd /mnt/mmcblk0p2/tce
cat <<"EOF" >>tune.sh
sleep 1
pkill udhcpc
sleep 1
pkill sshd
sync
echo 3 > /proc/sys/vm/drop_caches

EOF
sync
reboot

####################################

That'll be it.


Measure 5 -- Disable CPU throttling

To save power, all modern CPUs throttle the CPU in low demand situations.
That would happen while streaming at a load of 2%.  
Since the throttling process is quite intrusive - lurking and acting in the background all the time - we can just disable it. 
We can control the clock frequencies ourselves. We'll actually lower them in Measure 6.

There are two side effects I'm aware of:

1. Temperature will rise a little.
2. If Overclocking AND overvolting (over_voltage>0) AND force_turbo=1 is set,
    the RPI warranty bit gets set and that means you'll loose warranty for your RPI.
    Read this reference !  

    Disclaimer: As usual: It's your risk to run this exercise!


With this measure, we're just setting the force_turbo parameter.

Copy &  paste below after you've done a reboot and a ssh login again. 

###################################################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cd /mnt/mmcblk0p1
cat <<"EOF" >>config.txt
### Turn off CPU throttling 
force_turbo=1

EOF
sync
reboot

###################################################


Measure 6 -- Underclocking


What we can do now is "underclocking" the PI3. We don't need the 1200MHz 
default clock. Obviously that'll be causing quite some more power consumption and heat.
We don't want the 600MHz lower limit, which might be a little low. We also don't need high clock rates on the GPU side.

I ended up with a combination of clock rates that can all be divided by 200. It's been just a thought to avoid a mixup of several even and uneven frequencies. 

Copy &  paste below after you've done a reboot and a ssh login again. 


###################################################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cd /mnt/mmcblk0p1
cat <<"EOF" >>config.txt
### Introduce underclocking  of CPU, GPU and RAM
arm_freq=800
gpu_freq=200
core_freq=200
sdram_freq=400

EOF
sync
reboot

###################################################

Measure 7 -- Overclocking the SD-card

If you're using a rather new and highest quality SD-Card you might want to introduce
some overclocking. Since piCorePlayer mainly accesses the SD-card during boot and shutdown this measure won't show much of an impact. 
The clockrate being used will be 100MHz. It'll be smaller then the core-clock
by an even factor of two. 

I'm running 16G Sandisk Ultra HC 1 Class 10 ( sells usually @ 9.99 over here)

WARNING: 
Certain SD-cards might get corrupted or even damaged. It's 100% your risk if you run this exercise. If not sure leave this task alone. Don't blame me if you end up with a bricked SD -card!


###################################################
sudo su
grep -qs '/mnt/mmcblk0p1' /proc/mounts || {
   sudo mount /dev/mmcblk0p1 /mnt/mmcblk0p1
}
cd /mnt/mmcblk0p1
cat <<"EOF" >>config.txt
### Introduce overclocking  of SD-card
dtoverlay=sdhost,overclock_50=100

EOF

sed -i '/^\s*$/d' config.txt
sync
reboot

###################################################


Measure 8 -- Network paramaters

The default parameter used for the network interface can be tweaked a little. 
You might want to try this too.
We just add the required commands to the tune.sh script we're using already 
for killing processes in Measure 3+4.

Copy &  paste below after you've done a reboot and a ssh login again. 

####################################
sudo su
cd /mnt/mmcblk0p2/tce
cat <<"EOF" >>tune.sh
sleep 1
sysctl -w net.core.rmem_max=26214400
sysctl -w net.core.wmem_max=26214400
sysctl -w net.ipv4.tcp_rmem='4096 1048576 26214400'
sysctl -w net.ipv4.tcp_wmem='4096 1048576 26214400'
sysctl -w net.ipv4.tcp_mem='26214400 26214400 26214400'

EOF
sed -i '/^\s*$/d' tune.sh
sync
reboot

####################################


Measure 9 - Assign squeezelite to isolated CPU1

In Measure 2 we isolated CPU0 - actually we also isolated CPU1 already.  
The idea was to have all interrupts running on CPU0 exclusive. 
Now we're going one step further. We are going to assign squeezelite to a 2nd CPU CPU1 exclusive. CPU0 and CPU1 will then be used exclusively. 
The remaining 2 CPUs will be used for anything else that's going on. Which is not much. However. We try to leave no stone unturned with this exercise.

##################################
sudo su
cd /mnt/mmcblk0p2/tce
cat <<"EOF" >>tune.sh
sleep 1
taskset -cp 1 $(pgrep squeezelite)
EOF
sync
reboot
##################################


Measure 10 - Assign a higher priority to squeezelite 

During the squeezelite settings exercise we added "-p 45" to the settings.
With this we elevated the priority of just the output thread of squeezelite to 45.
The other three threads - the squeezelite process spawns 4 threads - are running 
at normal non-elevated priorities by default. Now we gonna lift these three too.

There's a range of 1-99 of priorities. If you start changing the priorities of processes
you have to make sure that a proper ranking stays in tact. E.g. the dwc_otg interrupts
being in charge for network and USB are fixed at prio 51. We simply shouldn't go
beyond that limit.


Now. The output thread has prio 45, using prio 44 for the rest of squeezelite will do.    

##################################
sudo su
cd /mnt/mmcblk0p2/tce
cat <<"EOF" >>tune.sh
sleep 1
chrt -f  -p 44 $(pgrep squeezelite)
EOF
sync
reboot



################################## 

Done!

........................................................................................................................................................


Wrap-Up

Hopefully you made it all the way down here. I'm pretty sure you did. 
I'm pretty confident you'll enjoy the result.


Don't forget to make a backup of your SD-card after this exercise!


**********

I rely on your feedback to get above
working reliable. 
For me above commands and actions are daily work. I have a hard time anticipating your potential issues in running this exercise.
I'd really appreciate if you'd just drop me a line, confirming that everything worked as
I assumed it would. Or you tell me that it isn't working and tell me what you've done.

Enjoy.

1 comment:

  1. Hi, I'm finding your blog both useful in tuning my Rpi3 with Picoreplayer and technically very interesting.

    ReplyDelete