# 22.6.高级主题

## 22.6.1. 调优

调整可调参数，使 ZFS 在不同的工作负载下表现最佳。

* `vfs.zfs.arc.max` 从 13.x 开始（12.x 使用 `vfs.zfs.arc_max`） - [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc) 的最大大小。默认值是除去 1 GB 后的所有 RAM，或者是所有 RAM 的 5/8，以较大的值为准。如果系统运行其他守护进程或进程可能需要内存，可以使用较小的值。可以在运行时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值，并在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中设置。
* `vfs.zfs.arc.meta_limit` 从 13.x 开始（12.x 使用 `vfs.zfs.arc_meta_limit`） - 限制用于存储元数据的 [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc) 的大小。默认值是 `vfs.zfs.arc.max` 的四分之一。如果工作负载涉及对大量文件和目录进行操作，或频繁进行元数据操作，则增加此值可以提高性能，但代价是较少的文件数据能适应 [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc)。可以在运行时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值，并在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中设置。
* `vfs.zfs.arc.min` 从 13.x 开始（12.x 使用 `vfs.zfs.arc_min`） - [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc) 的最小大小。默认值是 `vfs.zfs.arc.meta_limit` 的一半。可以调整此值，以防止其他应用程序挤出整个 [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc)。可以在运行时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值，并在 **/boot/loader.conf** 或 **/etc/sysctl.conf** 中设置。
* `vfs.zfs.vdev.cache.size` - 为池中每个设备预分配的缓存内存大小。总内存使用量是此值乘以设备数量。此值应在启动时设置，并在 **/boot/loader.conf** 中设置。
* `vfs.zfs.min_auto_ashift` - 池创建时自动使用的最低 `ashift`（扇区大小）。该值是 2 的幂。默认值为 `9`，表示 `2^9 = 512`，即 512 字节的扇区大小。为了避免 *写放大* 并获得最佳性能，应将此值设置为池中设备使用的最大扇区大小。\
  常见的驱动器有 4 KB 扇区。使用默认的 `ashift` 值 `9` 与这些驱动器会导致写放大。在这些设备中，单个 4 KB 写入的数据将以八次 512 字节写入的方式写入。ZFS 尝试在创建池时从所有设备读取原生扇区大小，但具有 4 KB 扇区的驱动器为兼容性考虑报告其扇区为 512 字节。通过在创建池之前将 `vfs.zfs.min_auto_ashift` 设置为 `12`（`2^12 = 4096`），可以强制 ZFS 使用 4 KB 块，从而获得最佳性能。

  强制使用 4 KB 块在计划进行磁盘升级的池中也非常有用。未来的磁盘将使用 4 KB 扇区，而 `ashift` 值在创建池后无法更改。

  在某些特定情况下，较小的 512 字节块大小可能更为合适。例如，在使用 512 字节磁盘用于数据库或虚拟机存储时，较小的块在进行小随机读取时会传输更少的数据。这可以在使用较小的 ZFS 记录大小时提供更好的性能。
* `vfs.zfs.prefetch_disable` - 禁用预取。值为 `0` 时启用，值为 `1` 时禁用。默认值为 `0`，除非系统内存小于 4 GB。预取通过将比请求的块大得多的数据块读取到 [ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-arc) 中，来期望稍后会需要这些数据。如果工作负载有大量随机读取，禁用预取可能会通过减少不必要的读取来提高性能。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.vdev.trim_on_init` - 控制是否对添加到池中的新设备执行 `TRIM` 命令。这可以确保 SSD 的最佳性能和寿命，但会额外耗时。如果设备已经进行了安全擦除，禁用此设置将加快新设备的添加过程。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.vdev.max_pending` - 限制每个设备的待处理 I/O 请求数。较高的值会保持设备命令队列满，从而可能提高吞吐量。较低的值则会减少延迟。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.top_maxinflight` - 每个顶级 [vdev](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-vdev) 的最大未决 I/O 数。限制命令队列的深度，以防止高延迟。该限制适用于每个顶级 vdev，即该限制对每个 [镜像](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-vdev-mirror)、[RAID-Z](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-vdev-raidz) 或其他 vdev 独立适用。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.l2arc_write_max` - 限制每秒写入 [L2ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-l2arc) 的数据量。此可调参数通过限制写入设备的数据量，延长 SSD 的使用寿命。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.l2arc_write_boost` - 将此可调参数的值添加到 `vfs.zfs.l2arc_write_max` 中，并在从 [L2ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-l2arc) 驱逐第一个块之前，提升 SSD 的写入速度。这个 "Turbo Warmup Phase" 减少了重启后空 [L2ARC](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-l2arc) 带来的性能损失。可以随时通过 [sysctl(8)](https://man.freebsd.org/cgi/man.cgi?query=sysctl\&sektion=8\&format=html) 调整此值。
* `vfs.zfs.scrub_delay` - 每次 I/O 操作之间的延迟时间（以 tick 为单位）在执行 [scrub](https://docs.freebsd.org/en/books/handbook/zfs/#zfs-term-scrub) 时。如果池有其他 I/O 操作，`scrub` 将在每个命令之间延迟。这项设置控制 `scrub` 产生的 IOPS（每秒 I/O 操作数）的上限。设置的粒度由 `kern.hz` 决定，默认是每秒 1000 个 tick。更改此设置会导致不同的有效 IOPS 限制。默认值为 `4`，因此 IOPS 限制为：1000 ticks/sec / 4 = 250 IOPS。使用 *20* 的值将使 IOPS 限制为：1000 ticks/sec / 20 = 50 IOPS。池上最近的活动限制了 `scrub` 的速度，具体限制

## 22.6.2.在 i386 上的 ZFS

ZFS 提供的一些特性对内存要求较高，因此在内存受限的系统上可能需要进行调整以提高效率。

### 22.6.2.1. 内存

作为最低要求，系统总内存应至少为 1 GB。推荐的内存量取决于池的大小以及使用的 ZFS 功能。一般经验法则是每 1 TB 存储需要 1 GB 内存。如果使用去重功能，则推荐的内存量为每 TB 存储 5 GB。虽然一些用户使用较少的内存来运行 ZFS，但在重负载下，系统可能会因内存耗尽而发生 panic。对于内存不足的系统，ZFS 可能需要进一步的调整。

### 22.6.2.2. 内核配置

由于 i386™ 平台的地址空间限制，i386™ 架构上的 ZFS 用户必须将此选项添加到自定义内核配置文件中，重新编译内核并重启：

```ini
options        KVA_PAGES=512
```

此选项扩展了内核地址空间，允许 `vm.kvm_size` 调优值突破 1 GB 的限制，或突破 PAE 的 2 GB 限制。为了找到最合适的值，可以将所需的地址空间（以 MB 为单位）除以 4。在这个例子中，`512` 代表 2 GB。

### 22.6.2.3. 启动加载器调优

在所有 FreeBSD 架构上增加 **kmem** 地址空间。一台具有 1 GB 物理内存的测试系统通过将以下选项添加到 **/boot/loader.conf** 并重新启动，从中受益：

```ini
vm.kmem_size="330M"
vm.kmem_size_max="330M"
vfs.zfs.arc.max="40M"
vfs.zfs.vdev.cache.size="5M"
```

有关 ZFS 调优的更详细建议，请参见 <https://wiki.freebsd.org/ZFSTuningGuide>。
