本帖最后由 中关村东路 于 2022-1-18 22:51 编辑
2 Roon Server
2.1 硬件配置Roon Server,我的思路是无扇加低延迟。最初用的AMD 5600x,用了半年多吧,猫头鹰风扇虽然声音小,知道有这么个风扇还是让我不能接受。 于是换成现在的Intel G6405 CPU,32G内存,海韵开关电源,分形Define13盘位机箱。 大机箱,大散热器,加上软件上的优化,可以保持无风扇35-45度之间。如果不需要很大的存储空间,也建议使用8-12盘位的机箱,一方面保留升级空间,另一方面用空位隔开可以降低硬盘温度。
1T nvme ssd作为系统盘并存放Roon索引和图片,2个2.5寸sata ssd作为下载盘,10个3.5寸hdd作为数据盘,其实机箱还有一个盘位,但是主板和HBA卡没空了。
Figure 2: 机箱提供了硬盘风扇,但是我没打开,写入量不大的话温度尚可。
Figure 3: 特地找出这张图,其中四色线是应对氦气盘做的转接电源线和电容,白色线连到HBA卡。
Roon官方推荐维护10万以上track应该使用I3或以上作为Roon Core,但实际上不使用升频、DSP、background audio analysis、on-demand audio analysis这几个功能时G6405加32G内存维护百万级别绰绰有余。 而尽量低配的CPU的好处是可以扔掉风扇。如果对性能有更高的要求,也强烈建议尽量用更大的散热设备,而不是引入风扇,因为风扇带来的各类噪音不易控制。当然,高手也可以使用高端静音风扇,并单独供电。 本文脚本是配合双核四线程的G6405编写的,但读者很容易修改成兼容i3/5/7/9或AMD的。
此外,因为Roon对多线程利用很差,所以我的Roon Server在BIOS里屏蔽了超线程。给Roon的关键线程RoonAppliance单独分配一个核心,除了zfs文件系统之外的其他线程分配在另外一个核心,并允许zfs利用所有核心。 当然,如果你的电脑核心很多,也可以限制zfs不使用Roon所用的核心。
2.2 操作系统和内核我使用的是Gentoo Linux操作系统,一则习惯,二则灵活。 这个系统中每个软件都针对本机硬件配置优化,需要自己编译,这需要消耗大量计算能力,无扇环境发热处理的不好的话可能不一定能撑得住。 最简单的办法是用其他电脑交叉编译。如果散热做的好,或使用其他操作系统可部分的避免这个问题。
Roon Server用systemd,pf-sources内核;Roon Bridge用openrc,rt-sources内核。 需要的模块都直接编译进内核,容量一般可以控制在10M以下。我的Roon Server的内核启动设置如下: - GRUB_CMDLINE_LINUX="intel_idle.max_cstate=0 vsyscall=none net.ifnames=0 ipv6.disable=1 nmi_watchdog=0 nosmt=force pcie_aspm=force"
- GRUB_CMDLINE_LINUX_DEFAULT="loglevel=3 quiet transparent_hugepage=never clocksource=hpet noibrs noibpb nopti nospectre_v2 nospectre_v1 l1tf=off nospec_store_bypass_disable no_stf_barrier mds=off mitigations=off"
复制代码
上面的设置除了nosmt,aspm,cstate和hpet之外几乎都是提高性能的,如果你的CPU强劲不设也可以。关掉超线程,打开aspm可以降低温度,还是值得设的。
我并没在这里直接分离CPU核心,而是用的systemd+cgroup,主要是为了灵活,也让zfs可以利用全部核心,提高IO效率。 而Roon Bridge功能极其单一,我用的又是全内存方案,不需要zfs,所以在内核引导时就隔离了CPU,后面会提到具体代码。
Roon Server内核设置有如下需要指出的,具体是什么可以查询手册我就不解释了,除了网络部分之外的多数不设置对性能的影响也都可以接受,或者可以在其他地方配置。还有很多其他设置没有列出来。
General Setup选择Preemptible kernel;关闭超线程;设置Optimize more for performance(-O3)。
Processor type and features设置Processor family为native optimizations autodetected by the compilor;设置Timer frequency为1000HZ。
Power management and ACPI options关闭suspend/hibernation,关闭ACPI中无用设置,CPUFreq governor选择performance,关闭其他选项。
Virtualization 我关闭了。如果有docker需求也可打开。
IO Schedulers我全都关闭了。如果不使用zfs,且使用机械硬盘,应按实际情况选择。
Networking support关闭除了Networking Options之外的无关选项,也可关闭ipv6。注意打开advanced congestion control里的bbr或者bbr2,关闭所有其他选项。
Device Drivers关闭除了本机使用的硬盘(nvme/sas/sata/scsi)、网卡、rtc时钟之外的所有驱动。fb、usb、kbd可以暂时留着用于调试,系统稳定之后也可以去掉。
2.3 硬盘文件系统系统盘和下载盘用ext4/xfs文件系统,可以降低内存占用; 音乐盘使用zfs raidz/raidz2,每四到六盘为一组,默认16G内存(一半物理内存)作为缓存即可,也可视稳定运行时候的内存剩余增加缓存,这可以利用内存缓存减少硬盘顺序读取的延迟; 分为两组的好处是一组有硬盘损坏掉线时可以立刻把关键数据拷贝出来。 另外两块硬盘我用于备份科研数据,使用zfs raid1,每次rsync -avP –no-p –no-g –chmod=ugo=rwX –delete –exclude-from=$rexclude备份后打snapshot,Roon Server的数据库(主要包括索引和海量图片)备份也放在这。
这里需要指出,使用raid是便于组织数据,并利用zfs的缓存优势。重要数据还是有必要备份的。
2.4 磁盘调度器因为ssd性能好,改为none调度器即可;zfs自己有自己的调度器,所以也设置成none调度器。 - cat /etc/udev/rules.d/60-ioschedulers.rules
- ACTION=="add|change", KERNEL=="nvme[0-9]n[0-9]", ATTR{queue/scheduler}="none"
- ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="0",ATTR{queue/scheduler}="none"
- ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="none"
复制代码
zfs只设置了zpool ashift=12,zfs atime=off两个参数。备份盘加compression=on参数可降低IO提高性能,音乐盘压缩没什么用不要加。 - zpool create music0 raidz -m none -o ashift=12 ata-WDC_WUHxxx ata-WDC_WUHyyy ...
- zfs set atime=off music0
- zfs create -o mountpoint=/storage/music/classic music0/classic
- zfs create -o mountpoint=/storage/music/jazz music0/jazz
复制代码
2.5 BBR2和前面内核部分对应,如果你编译中选择了bbr一代要相应修改。 - cat /etc/sysctl.d/10-custom-kernel-bbr.conf
- net.core.default_qdisc=fq
- net.ipv4.tcp_congestion_control=bbr2
- net.ipv4.tcp_ecn=1
复制代码
2.6 watchdog等其他设置Roon Server管理的文件多的话需要设置第一条,其他各类杂项设置可以自己调整。 - cat /etc/sysctl.d/15-max-user-watches.conf
- fs.inotify.max_user_watches = 2093952
- kernel.nmi_watchdog = 0
- vm.dirty_writeback_centisecs = 6000
复制代码
2.7 安装Roon Server 如果用Gentoo Linux操作系统的,可以使用我在github维护的源zhjie:gentoo_repo中直接安装。当然也可以使用其他方法例如官网下载手动安装。 需要指出两点,第一是Roon Server启动过程中需要依赖alsa,但实际上却不需要内核中编译alsa驱动。 第二点,如果不需要转换格式,例如升频,Roon Server并不像官方宣称的依赖于ffmpeg,所以我的ebuild提供了编译和依赖选项,也提供选择使用systemd/rc。 必须依赖的只有icu和alsa-lib。 在下面例子里的“systemd -ffmpeg”表明,我的Roon Server用systemd管理,而不依赖于ffmpeg。 - eix RoonServer -I
- [I] media-sound/RoonServer [1]
- Available versions: (~)1.8.884^md {ffmpeg systemd}
- Installed versions: 1.8.884^md(11:33:07 PM 01/01/2022)(systemd -ffmpeg)
- Homepage: https://roonlabs.com/index.html
- Description: music player sever
- [1] "zhjie-repo" /var/db/repos/zhjie-repo
复制代码
2.8 优化Roon Server的界面响应 本小节设置优先级主要是优化界面、搜索、增加新音乐等的响应,并不影响音乐播放。 如果你有多个CPU核心,那么建议在这里的“AllowedCPUs=0,1”只分配给Roon两个即可,其中一个给RoonApplicance,一个给其他,再多了Roon也是针对这个任务单线程计算。 - cat /etc/systemd/system/roonserver.service.d/override.conf
- [Service]
- Nice=-20
- AllowedCPUs=0,1
复制代码
2.9 给Roon Server关键线程隔离CPU 给播放音乐最重要的RoonAppliance分配单独的CPU核心,下面的脚本里是CPU1,而把RAATServer和RoonServer通过cgroup和taskset分配到其他核心,即CPU0,以避免索引新增音乐时干扰当前的音乐播放。
注意Roon Server的RAATServer其实是可以关掉的,因为这个线程是用来管理本机解码器的,我连在Roon Bridge上了在这就不需要了。 但我关了之后发现Roon会经常轮询产生没找到的错误日志,我就又打开了,反正也不占用资源。 - sed -i 's/exec "$HARDLINK" "$SCRIPT.dll" "$@"/exec taskset -c 1 "$HARDLINK" "$SCRIPT.dll" "$@"/g' \
- /opt/RoonServer/Appliance/RoonAppliance
- sed -i 's/exec "$HARDLINK" "$SCRIPT.dll" "$@"/exec taskset -c 0 "$HARDLINK" "$SCRIPT.dll" "$@"/g' \
- /opt/RoonServer/Appliance/RAATServer
- sed -i 's/exec "$HARDLINK" "$SCRIPT.dll" "$@"/exec taskset -c 0 "$HARDLINK" "$SCRIPT.dll" "$@"/g' \
- /opt/RoonServer/Server/RoonServer
复制代码
上面优化的依据是官方提供的如下关于Roon Server/Bridge各个线程的作用:
RoonAppliancewhere the “Roon Core” lives
RAATServermakes this device available as a networked endpoint that can play audio
RoonServerhandles all of the core functions(library management, Tidal, DSP, etc)
RoonBridgeHelpermanages some administrative details for Roon Bridge [1] https://community.roonlabs.com/t/what-are-these-different-processes/20335/3 [2] https://community.roonlabs.com/t/roonbridge-roonserver-change-priority-of-the-process/32470/2
2.10 给其他进程分配CPU前面说过,我把CPU1分配给了RoonAppliance,所以限制其他所有进程,只使用CPU0。如果你有更多核心,也可以改为AllowedCPUs=2,3,记得把RoonAppliance所在的CPU1留下来就可以。 在这里systemd的方便就显示出来了,恩,真很方便。当然也也可以像前面Roon Server一样使用“override.conf”实现。 其中尤其需要注意的是sshd,每次远程登录之后执行的命令都会继承sshd的cgroup,所以如果这里不限制可能会导致执行的命令占用Roon的资源。 - systemctl set-property --runtime -- systemd-udevd.service AllowedCPUs=0
- ...
- systemctl set-property --runtime -- sshd.service AllowedCPUs=0
复制代码
- systemctl set-property --runtime -- systemd-udevd.service AllowedCPUs=2,3
- ...
- systemctl set-property --runtime -- sshd.service AllowedCPUs=2,3
复制代码
|