Linux / NVMe | APST 不完全总结
阿里云国内75折 回扣 微信号:monov8 |
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6 |
本文简要地从 Linux
内核或者 NVMe
的角度对 APST
进行不完全总结。
更新2023 / 2 / 4
Linux / NVMe | APST 不完全总结
总览
快速可靠的 NVMe SSD
彻底改变了数据存储。但是NVMe SSD
技术有一个缺点高功耗。 幸运的是 NVMe
规范提供很多电源管理功能。
NVMe
电源管理非常重要以在平台散热与 SSD
消耗的总功率之间达成可接受的平衡。
台湾的企业 SSD
制造商 Phison Electronics
公司产品架构总监 Imran Hirani
表示即使规格定义了 SSD
的最大功率主机也可以使用 NVMe
功率状态来改变 SSD
的消耗量。这种改变是基于所需的访问方式以及系统的最大可用热解决方案和气流。 Hirani
说“由于客户端驱动器大部分时间处于空闲状态因此客户端驱动器使用非工作电源状态来延长电池寿命。”
关键电源管理技术和功能
主机可以通过 3
种不同的方式访问 NVMe
电源管理功能
- 为了为自主电源状态转换功能
Autonomous Power State Transition
设置电源状态条件请使用set feature
命令FID=0xC, APST
。然后SSD
将根据设置的条件转换到不同的电源状态。 - 使用
set feature
命令进行电源管理以更改当前SSD
电源状态。 - 使用
set feature
命令用于主机控制的热管理以建立两个温度阈值。当设备达到设定温度后设备将自动转换到低功耗状态。
NVMe
电源管理基于工作负载和可用的散热平台。对于客户端、数据中心和企业级固态硬盘会有所不同。
Hirani
说“对于客户端固态硬盘由于驱动器大多数时候都处于空闲状态因此 APST NVMe
电源管理是最佳方法因为驱动器将根据设置的空闲时间限制过渡到较低的电源状态。” 同时数据中心 SSD
通常使用 NVMe
电源管理功能来限制特定工作负载的最大固态硬盘性能以在性能和散热预算要求之间取得平衡。
Hirani
表示“由于企业级 SSD
在大多数时间都是活跃状态因此它们可以使用热管理功能来确保设备不会过热并触发热关机条件。”
NVMe
电源管理功能可在电源、性能、产品可靠性和客户体验之间找到可接受的平衡。但是如果企业未正确配置 NVMe
电源管理则存在风险。
这些风险包括以下内容
- 无法正确管理
SSD
的活跃电源这会导致产生过多热量这有可能导致可用系统气流无法充分冷却SSD
。Hirani
说“在最坏的情况下SSD
可能达到其热关机极限并且会关机”。 - 在非运行电源模式下驱动器无法转换为低功耗模式时驱动器将继续消耗功率即使驱动器处于空闲状态也是如此。
Hirani
警告说“这会更快耗尽笔记本电脑/笔记本电脑中的电池导致糟糕的客户体验。” 尽管NVMe
电源状态提供各种节能级别但进入和退出每个状态所需的时间也需要权衡。Hirani
说“最低功率状态将花费最长的时间以进入和退出。不考虑进入和退出延迟可能会导致性能降低或响应时间延长。”
kernel
概念
在 drivers/nvme/host/core.c
1 中关于 APST
设定的源码如下
/*
* APST (Autonomous Power State Transition) lets us program a table of power
* state transitions that the controller will perform automatically.
*
* Depending on module params, one of the two supported techniques will be used:
*
* - If the parameters provide explicit timeouts and tolerances, they will be
* used to build a table with up to 2 non-operational states to transition to.
* The default parameter values were selected based on the values used by
* Microsoft's and Intel's NVMe drivers. Yet, since we don't implement dynamic
* regeneration of the APST table in the event of switching between external
* and battery power, the timeouts and tolerances reflect a compromise
* between values used by Microsoft for AC and battery scenarios.
* - If not, we'll configure the table with a simple heuristic: we are willing
* to spend at most 2% of the time transitioning between power states.
* Therefore, when running in any given state, we will enter the next
* lower-power non-operational state after waiting 50 * (enlat + exlat)
* microseconds, as long as that state's exit latency is under the requested
* maximum latency.
*
* We will not autonomously enter any non-operational state for which the total
* latency exceeds ps_max_latency_us.
*
* Users can set ps_max_latency_us to zero to turn off APST.
*/
static int nvme_configure_apst(struct nvme_ctrl *ctrl)
{
struct nvme_feat_auto_pst *table;
unsigned apste = 0;
u64 max_lat_us = 0;
__le64 target = 0;
int max_ps = -1;
int state;
......
因此APST
是一项允许 NVMe
Controller
在 NVMe
SSD
内按照可配置规则在电源管理状态之间自主切换的功能。 NVMe
Controller
指定进入和退出每个省电状态 power-save state
需要多少微秒内核使用此信息来配置 NVMe
Controller
内的状态转换规则 2。
设置
此前在部分版本的 kernel
的使用中发现倘若 BIOS
或 Nvme
在加载驱动前使能 APST
那么 APST
无法被永远禁止并且会忽略相关的特定内核参数设置 3。
相关的特定内核参数是 default_ps_max_latency_us
通过
$ cat /sys/module/nvme_core/parameters/default_ps_max_latency_us
可查询其默认值。
更改可通过修改 /etc/default/grub
文件中相应的行为 nvme_core.default_ps_max_latency_us=0
然后 update-grub
。
修改结果可通过 $ cat /proc/cmdline
确认输出结果
BOOT_IMAGE=/boot/vmlinuz-4.10.0-22-generic.efi.signed root=UUID=365f1a9c-9598-4ad5-a387-d02f771767a1 ro quiet splash nvme_core.default_ps_max_latency_us=0 vt.handoff=7
其中nvme_core.default_ps_max_latency_us=0
出现证明此前的修改已并入启动配置中。
确定当前设备的 APST
功能是否开启与否可通过 $ sudo nvme get-feature -f 0x0c -H /dev/nvme0
命令命令的输出结果将显示是 Didsabled
或者 Enabled
。
即使可暂时通过手动修改参数禁止 APST
只要进行 reboot
其 APST
功能会被重新启用。
问题
当 APST
Enabled
时设备进入低功耗模式后无法在预计时间内恢复为正常模式或者除非重启 Controller
否则无法醒来的话会让 kernel
不高兴。
为避免此种问题可以设定内核参数最大允许从 APST
状态管理醒来时间为 0
以禁止 APST
功能。
如果 Nvme
Controller
的 APST
功能无法使用Controller
则只能进入 kernel
要求的低功耗状态。
最好的解决方法是NVMe disk firmware
确保 APST
功能正常使用或者至少drive
不预期无法发生的事发生比如不给 APST
功能过于乐观的电源状态切换时间并且 / 或者不允许任何可能会导致 Controller
失败的 APST
功能。
如果证明该问题可以通过编程 APST
来完全避免最深的节能状态那么可能可以通过创建一个 kernel-level
的 workaround
。
在 kernel
中许多设备的驱动都有 quirk table
用于指定特定硬件模型的解决方法 4。
在 NVMe
中 5以下是会触发 driver
中的各种 workaround
代码的 NVME_QUIRK_
设置。
static const struct pci_device_id nvme_id_table[] = {
{ PCI_VDEVICE(INTEL, 0x0953), /* Intel 750/P3500/P3600/P3700 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
{ PCI_VDEVICE(INTEL, 0x0a53), /* Intel P3520 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
{ PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
{ PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
NVME_QUIRK_DEALLOCATE_ZEROES, },
{ PCI_VDEVICE(INTEL, 0xf1a5), /* Intel 600P/P3100 */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_MEDIUM_PRIO_SQ |
NVME_QUIRK_NO_TEMP_THRESH_CHANGE |
NVME_QUIRK_DISABLE_WRITE_ZEROES, },
[...]
请注意一个已经存在的名为 NVME_QUIRK_NO_DEEPEST_PS
的 quirk
设置它可以防止状态转换到最深的电源管理状态。
如果你的 NVMe
的 APST
问题与英特尔 600P/P3100
和 ADATA SX8200PNP
的解决方案相同那么只需要像这样编写一条新的 quirk table entry
替换 <尖括号> 内的内容使用适当的值您可以使用 lspci -nn
获取它们
{ PCI_DEVICE(<PCI vendor ID>, <PCI product ID of the SSD>), /* <specify make/model of SSD here> */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS, },
并使用此修改重新编译 kernel
。
如果设置 NVME_QUIRK_NO_DEEPEST_PS
结果无法解决问题则可能需要实施新的 quirk
。这可能会更复杂并且可能需要一些实验或理想情况下来自 SSD
的信息以找出究竟需要做什么来避免这个问题并且可能需要与 Linux
NVMe
驱动程序维护者讨论实现它的最佳方法。