Paspberry Pi4+OpenMediaVaultでTimemachineバックアップ。備忘録およびパフォーマンス最適化

## はじめに

RaspberryPi4にOpenMediaVaultをインストールして、MacのTimemachineバックアップを以前から行っていましたが、ちょっと設定をいじったのでメモ。

## Mac側のTimemachineバックアップ設定

しりませんでしたが、MacOS Sonomaでは、Timemachineバックアップディスクを新規作成する場合、バックアップのサイズを指定できるようになっていました。複数Macでバックアップを取る際、容量の取り合いになって困っていたのでこれは助かります。

## OpenMediaVaultのディスクマウントオプション

USB HDDをマウントしていますが、writeが平均で30MB/sと今一つの印象。/etc/fstabでマウントオプションを確認してみると、noatime,nodiratimeが指定されていません。このオプションを付けてみようと思います。

### OpenMediaVaultの設定をいじる

:::note info
これはOpenMediaVault 5での話なので、最新のバージョンでは状況が異なる可能性があります。
:::

/etc/fstabの先頭にコメントがありますが、このファイルを直接変更しても、OpenMediaVaultでのGUI設定で上書きされてしまいます。

変更の仕方はここに記載があります:
https://docs.openmediavault.org/en/stable/various/fs_env_vars.html

- /etc/openmediavault/config.xml をエディット

`<opts>defaults,nofail,noexec..`のような記述があるので、noatime,nodiratime,を追加

- /etc/default/openmediavault をエディット

/etc/fstabに記載してあったマウントオプションを参考に以下の設定を追加

`OMV_FSTAB_MNTOPS_EXT3="noatime,nodiratime,defaults,nofail,user_xattr,usrjquota=aquota.user,grpjquota=aquota.group,jqfmt=vfsv0,acl"`

## CPUのSoft-IRQの割合が高い

Timemachineバックアップ時、Raspberry piのSoft-IRQの割合が高いのが気になります。load avarageも3程度となります。

![スクリーンショット 2024-11-16 17.46.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12960/836e9891-0c96-0747-f70d-0d4a8b211938.png)


ChatGPTのアドバイスをもとに調査してみました。

```
$ cat /proc/softirqs
                    CPU0       CPU1       CPU2       CPU3       
          HI:          1          0          0          1
       TIMER:     348449     126319     149574     315481
      NET_TX:    5416526      33845      46677      26558
      NET_RX:   19357623     270622     240783     236306
       BLOCK:     117191      94347     105094      89005
    IRQ_POLL:          0          0          0          0
     TASKLET:    3276370          0          0         57
       SCHED:     579815     333740     314275     477053
     HRTIMER:         33          1          0          1
         RCU:     533660     384176     352263     396435
```

結果を見ると、NET_TX/RXのネット関連の割り込みがCPU0に集中しています。

```
$ cat /proc/interrupts
           CPU0       CPU1       CPU2       CPU3       
  9:          0          0          0          0     GICv2  25 Level     vgic
 12:    1808398    1206917    1222136    1386202     GICv2  30 Level     arch_timer
 13:          0          0          0          0     GICv2  27 Level     kvm guest vtimer
 19:          0          0          0          0     GICv2 107 Level     fe004000.txp
 20:     579109          0          0          0     GICv2  65 Level     fe00b880.mailbox
 23:        348          0          0          0     GICv2 153 Level     uart-pl011
 24:          0          0          0          0     GICv2 129 Level     vc4 hvs
 27:          0          0          0          0     GICv2 114 Level     DMA IRQ
 29:          0          0          0          0     GICv2 116 Level     DMA IRQ
 34:          0          0          0          0     GICv2 141 Level     vc4 crtc
 35:          0          0          0          0     GICv2 142 Level     vc4 crtc, vc4 crtc
 36:          0          0          0          0     GICv2 133 Level     vc4 crtc
 37:          0          0          0          0     GICv2 138 Level     vc4 crtc
 38:          0          0          0          0  interrupt-controller@7ef00100   0 Edge      vc4 hdmi cec tx
 39:          0          0          0          0  interrupt-controller@7ef00100   1 Edge      vc4 hdmi cec rx
 42:          0          0          0          0  interrupt-controller@7ef00100   4 Edge      vc4 hdmi hpd connected
 43:          0          0          0          0  interrupt-controller@7ef00100   5 Edge      vc4 hdmi hpd disconnected
 44:          0          0          0          0  interrupt-controller@7ef00100   8 Edge      vc4 hdmi cec tx
 45:          0          0          0          0  interrupt-controller@7ef00100   7 Edge      vc4 hdmi cec rx
 48:          0          0          0          0  interrupt-controller@7ef00100  10 Edge      vc4 hdmi hpd connected
 49:          0          0          0          0  interrupt-controller@7ef00100  11 Edge      vc4 hdmi hpd disconnected
 50:        818          0          0          0     GICv2  66 Level     VCHIQ doorbell
 51:      97437          0          0          0     GICv2 158 Level     mmc0
 52:          0          0          0          0     GICv2  48 Level     arm-pmu
 53:          0          0          0          0     GICv2  49 Level     arm-pmu
 54:          0          0          0          0     GICv2  50 Level     arm-pmu
 55:          0          0          0          0     GICv2  51 Level     arm-pmu
 58:    6548408          0          0          0     GICv2 189 Level     eth0
 59:    3929203          0          0          0     GICv2 190 Level     eth0
 65:          0          0          0          0     GICv2 106 Level     v3d
 67:    1136716          0          0          0  BRCM STB PCIe MSI 524288 Edge      xhci_hcd
IPI0:     24196      31512      32708      25727       Rescheduling interrupts
IPI1:    726130    1850062    1460694    1558956       Function call interrupts
IPI2:         0          0          0          0       CPU stop interrupts
IPI3:         0          0          0          0       CPU stop (for crash dump) interrupts
IPI4:         0          0          0          0       Timer broadcast interrupts
IPI5:    157211     104530     112406     153861       IRQ work interrupts
IPI6:         0          0          0          0       CPU wake-up interrupts
```

ネットワークeth0およびxhci_hcd（USB HDD関連）の割り込みが、CPU0だけに集中していることがわかります。まさにネットミーム動画[Multiple Core Dance](https://www.youtube.com/watch?v=MNhubpzhs-Q)状態。

これは割り込みを分散化してくれるirqbalanceサービスが有効化されていないのが原因かもとのことで、まずそのサービス状態を確認。

```
sudo systemctl status irqbalance
Unit irqbalance.service could not be found.
```

なぜかパッケージがインストールされていません。`sudo apt install irqbalance`実行後、再度有効化します。

```
$ sudo systemctl enable irqbalance
Synchronizing state of irqbalance.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable irqbalance
$ sudo systemctl start irqbalance
$ sudo systemctl status irqbalance
● irqbalance.service - irqbalance daemon
   Loaded: loaded (/lib/systemd/system/irqbalance.service; enabled; vendor preset: enabled)
   Active: active (running) since Sat 2024-11-16 14:16:01 JST; 1min 48s ago
```

念の為再起動して、効果があるか確認

```
$ cat /proc/interrupts | grep eth0
 58:     403301          0          0          0     GICv2 189 Level     eth0
 59:     146274          0          0          0     GICv2 190 Level     eth0
```

残念ながら全く効果なし。

調べたところ、Raspberry Pi3までは割り込みは1つのCPUに固定でどうしようもないのですが、Raspberry Pi4だとちょっと違う模様。それについては以下参照。

## Raspberry Pi4でのネットワークパフォーマンス最適化

:::note info
Raspberry Pi OS Lite Busterでの話なので、最新バージョンでは状況が異なる可能性があります。また、この内容はRaspberry Pi4限定となります。
:::

Soft IRQ周りの最適化について、参考になる記事が見つかりました

https://tomcore.io/docs/articles/RaspberryPI/raspberry-pi-4b-network-performance/

この記事を参考に割り込みを処理するCPUを指定していきます。まず、以下のコマンドでeth0のread/writeを処理する割り込み番号を取得（以下の例だと58, 59)

```
$ cat /proc/interrupts | grep eth0
 58:     867096          0          0          0     GICv2 189 Level     eth0
 59:     454744          0          0          0     GICv2 190 Level     eth0
```

得られた番号をもとに、以下のコマンドで割り込み番号58にはCPU1を、59にはCPU2を指定します。

```
$ sudo sh -c 'echo 2 > /proc/irq/58/smp_affinity'
$ sudo sh -c 'echo 4 > /proc/irq/59/smp_affinity'
```

設定が意図通り機能していることを確認

```
$ cat /proc/interrupts 
           CPU0       CPU1       CPU2       CPU3       
 58:     869797      17311          0          0     GICv2 189 Level     eth0
 59:     456694          0      11393          0     GICv2 190 Level     eth0
```

ちゃんとCPU1, CPU2に割り込み処理が分散されています。

記事によると、割り込みを全てCPU0で行う場合、片方向通信だとほぼ理論値の1Gbpsに近い速度が出るものの、双方向通信時にはそれぞれ500Mbps程度になるとのこと。read/writeの割り込み処理を別CPUで行うことで、パフォーマンスの改善ができるそうです。

記事をもとに、eth0の割り込みを別処理する設定と、パケットステアリングの設定を行うスクリプトを作成。**このスクリプトはRaspberry Pi4専用です。**

```raspi4_network_optimization.sh
#!/bin/bash
###############################################################
# Raspberry Pi4 (ONLY) Network Optimization 
# https://tomcore.io/docs/articles/RaspberryPI/raspberry-pi-4b-network-performance
###############################################################

if grep -q "Raspberry Pi 4" /proc/device-tree/model; then
#    echo "This is a Raspberry Pi 4."
else
    echo "This is NOT a Raspberry Pi 4." >&2
    exit 1
fi

###############################################################
# Network Performance Optimization 1 - Interrupt CPU Affinity
###############################################################

# Get IRQ numbers for eth0
irq_numbers=$(cat /proc/interrupts | grep eth0 | awk '{print $1}' | sed 's/://')

# List of values to set in smp_affinity
affinity_values=(2 4)

i=0

# Process each IRQ number
for irq in $irq_numbers; do
  # Get the value to set
  value=${affinity_values[$i]}

  # Apply the setting
  echo "$value" > /proc/irq/$irq/smp_affinity
  echo "Set smp_affinity to $value for IRQ $irq"

  i=$((i + 1))
done

###############################################################
# Network Performance Optimization 2 - Paket Steering
###############################################################

echo f >/sys/class/net/eth0/queues/tx-0/xps_cpus
echo f >/sys/class/net/eth0/queues/tx-1/xps_cpus
echo f >/sys/class/net/eth0/queues/tx-2/xps_cpus
echo f >/sys/class/net/eth0/queues/tx-3/xps_cpus
echo f >/sys/class/net/eth0/queues/tx-4/xps_cpus
echo f >/sys/class/net/eth0/queues/rx-0/rps_cpus
```

まず手動実行して動作が確認できたら、`/etc/rc.local`で実行するように追記しておきます。

## 結果

はたしてバックアップの速度があがったのか、統計情報を見てみます。

![スクリーンショット 2024-11-21 23.13.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12960/15ed5033-5b2b-de89-087f-af5d7567d001.png)

15 Novが最適化前、それ以降が最適化後です。
条件が同一ではないとはいえ、改善が見られませんね... 残念ながら不発に終わりました。

![スクリーンショット 2024-11-21 23.17.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12960/a9ae03e0-4793-64f3-4933-b1e27a948e0d.png)

一応Soft-IRQは減っているように思えます。