Page 1 of 1

My killer optimizations for Gentoo Linux on Raspberry Pi 3 B+.

Posted: Mon Mar 25, 2019 2:38 pm
by crocket
Reducing Writes
  • Disable anacron USE flag in cronie because anacron writes to disk. Cronie doesn't write to disk.
  • Don't run an SMTP server because it keeps its states on disk. An SMTP client like msmtp doesn't keep its runtime states on disk.
  • Redirect non-essential writes to RAM through /etc/fstab

    Code: Select all

    tmpfs /tmp tmpfs mode=1777,noatime 0 0
    tmpfs /var/tmp tmpfs mode=1777,noatime 0 0
    tmpfs /var/log tmpfs mode=0755,noatime 0 0
    tmpfs /var/cache tmpfs mode=0755,noatime 0 0
    tmpfs /var/lib/dhcpcd tmpfs mode=0755,noatime 0 0
    tmpfs /var/lib/ntp tmpfs mode=0755,uid=ntp,gid=ntp,noatime 0 0
    tmpfs /var/lib/misc tmpfs mode=0755,noatime 0 0
    tmpfs /var/lib/run tmpfs mode=0755,noatime 0 0
    tmpfs /var/lib/syslog-ng tmpfs mode=0700,noatime 0 0
    tmpfs /lib/rc/cache tmpfs mode=0755,noatime 0 0
    # You may want to create /lib/rc/console before booting Gentoo Linux.
    tmpfs /lib/rc/console tmpfs mode=0755,noatime 0 0
    tmpfs /lib/rc/tmp tmpfs mode=0755,noatime 0 0
  • Set sync=disabled and logbias=throughput in the root ZFS dataset so that ZIL is disabled. ZIL doubles write amplification factor.
  • Keep /usr/portage and /var/db/repos empty on raspberry pi because updating overlays on raspberry pi consumes precious microSD write cycles. I build everything in an arm64 chroot.
  • You can batch writes by updating everything in a ZFS arm64 chroot, taking a ZFS snapshot, and sending the ZFS snapshot to Raspberry Pi.
  • Set SAVE_ON_STOP="no" in /etc/conf.d/alsasound to prevent /etc/init.d/alsasound from writing to disk during shutdown.
  • Disable less history logging in ~/.bash_profile. With loksh, it's ~/.profile

    Code: Select all

    export LESSHISTFILE="-"
  • Disable bash history logging in ~/.bashrc. With loksh, you don't need to unset HISTFILE.

    Code: Select all

    unset HISTFILE
  • Disable shada and swapfile in ~/.config/nvim/init.vim

    Code: Select all

    set shada=""
    set noswapfile
  • Prevent wpa_cli from writing to disk
    • Code: Select all

      ln -s /tmp/[USER]-wpa_cli_history ~/.wpa_cli_history
    • /etc/cron.daily/delete-wpa_cli_history

      Code: Select all

      #!/bin/sh
      
      rm -f /tmp/*-wpa_cli_history
  • Disable python interactive session logging
    • Add the following line to ~/.profile

      Code: Select all

      export PYTHONSTARTUP="$HOME/.pythonrc"
    • ~/.pythonrc

      Code: Select all

      import readline
      readline.set_auto_history(False)
  • Disable writing to /etc/resolv.conf
    • Add the following line to /etc/dhcpcd.conf.

      Code: Select all

      nohook resolv.conf
      Make sure it doesn't belong to a specific interface. For example,

      Code: Select all

      interface wlan0
      nohook resolv.conf
      is not going to prevent dhcpcd from overwriting /etc/resolv.conf
    • Manually write /etc/resolv.conf

      Code: Select all

      # For example, Google DNS
      nameserver 8.8.8.8
      nameserver 8.8.4.4
      
  • Check if anything is actually written by comparing differences between the lastest snapshot and the current file system.
    • In case of ZFS, the command is

      Code: Select all

      zfs diff [email protected] dataset
    • /etc/mtab can differ because it is a symlink into /proc.
Other optimizations
  • Use net-misc/ntp instead of net-misc/openntpd
    • Because Raspberry Pi doesn't save time in hardware clock, time needs to be set after boot. net-misc/openntpd waits for only 15 seconds for an internet connection. After 15 seconds, openntpd fails to set the time automatically forever. It can often take more than 15 seconds for dhcpcd to fetch an IP address. On the other hand, net-misc/ntp waits for an internet connection in the background and sets the time properly in a few minutes.
  • /boot/cmdline.txt

    Code: Select all

    rootwait rootfstype=zfs root=ZFS=rpi/ROOT/gentoo zfs.zfs_arc_max=67108864 dwc_otg.lpm_enable=0 console=tty1 console=ttyAMA0,115200
    • zfs.zfs_arc_max=67108864 limits the maximum size of ZFS ARC to 64MB because Raspberry Pi 3 B+ has only 1GB of RAM.
    • dwc_otg.lpm_enable=0 disables USB controller power management which can lead to unexpected problems.
    • console=tty1 console=ttyAMA0,115200 displays kernel messages on both tty1 and UART console and shows OpenRC messages only on UART console. UART console is a lot more convenient than an HDMI cable and a USB keyboard.
  • /boot/config.txt

    Code: Select all

    # have a properly sized image
    disable_overscan=1
    
    # Disable sound over HDMI
    hdmi_drive=1
    
    # gpu_mem is for closed-source driver only; since we are only using the
    # open-source driver here, set low
    gpu_mem=16
    
    initramfs initramfs-4.19.30-v8+.img followkernel
    
    dtparam=audio=on
    
    dtoverlay=pi3-disable-bt
    
    audio_pwm_mode=2
    • dtoverlay=pi3-disable-bt disables bluetooth and assigns PL011 module to GPIO UART pins because miniUART and bluetooth suck.
    • dtparam=audio=on enables audio.
    • initramfs initramfs-4.19.30-v8+.img followkernel makes linux kernel use initramfs-4.19.30-v8+.img as the initial ramdisk. This initial ramdisk contains ZFS kernel modules needed for booting ZFS root.
    • gpu_mem=16 because I don't need a graphical user interface from Raspberry Pi.
    • audio_pwm_mode=2 is an undocumented experimental driver that improves onboard audio quality.