Mac 的内置硬盘速度那么快,它是不是「作弊」了|免费试读( 二 )


诚然 , 从日常使用角度而言 , 前一项数据是用户直接感知的「写入性能」 , Mac 内置硬盘也确实有亮眼表现 。 但一旦发生断电等故障 , 那些还滞留在驿站的快件(缓冲区未落盘的数据)就有丢失的风险 。
此外 , 快件从驿站派送上门的顺序 , 往往不同于到达驿站的顺序;派件员(硬盘主控)可能为了省时省事等目的将其重新排列组合 。 这在平时也无妨 , 但对于数据库日志、文件系统日志等特殊场合 , 常常要求关于一项操作的记录必须先于这项操作本身落盘(好比从银行存取现金 , 一定是先记账、再动钱) 。 这些预写日志(write-ahead log , WAL)会被打上称为「写入屏障」(write barrier)的标签 , 享受「优先派送」的待遇 , 它的落盘效率直接影响到后续操作何时能进行 。
因此 , 如果说 Martin 测试的前一项数据代表了数据 日常写入的效率 , 那么后一项数据则代表了 数据落袋为安的效率 , 同样不能忽视 。 而正是在这项性能上 , Mac 发生了翻车 。
不仅如此 , Martin 还宣称 发现了 macOS 的一项「作弊」行为 。
在测试落盘性能时 , 他最初使用了 POSIX标准定义的 fsync系统调用 。 POSIX 是一套旨在促进操作系统相互兼容的接口标准 , Linux 是在 POSIX 标准的指导下开发的(尽管并未完全遵循) , 而 macOS 更是通过了其认证 。 因此按理说 , 两个系统执行 fsync的结果应该是一致的 , 也就是像标准所规定的那样 , 「强制对缓冲中的数据执行物理写入 , 并确保系统崩溃等错误后 , 截至调用前的所有数据均已录入磁盘」 。
实际情况并非如此 。 Martin 发现 , Linux 的确执行了 fsync所附加的冲刷缓冲动作 , 测出的写入效率也比不冲刷缓冲时相应降低 。 但如果在一台 MacBook Air 上用 fsync写入数据 , 五秒之后通过 PD 协议发去一条强制重启指令 , 这些理论上应该落盘的数据还是会丢失 。 他又换了一台 Mac mini , 用 fsync 写入数据五秒之后直接拔了插头 , 同样出现了丢数据的情况 。
这种现象只有一种可能原因 , 那就是 macOS「无视」了fsync所附加的落盘要求 。
的确 , 如果你在 macOS 下查阅 fsync的手册页面(可以在终端执行 man fsync查阅)中 , 就能看到这样一段说明:

注意 , 尽管 fsync 将所有数据从宿主冲刷到驱动器(即「永久存储设备」) , 该驱动器自身可能在 相当长的时间内都并不会将数据在物理意义上写入盘片 , 并且可能不依先后顺序写入 。 具体而言 , 如果驱动器断电、操作系统崩溃 , 应用程序的数据 可能只被部分写入 , 或完全没有写入 。 磁盘还可能重新排序数据 , 导致 后来的写入还存在 , 而早先的写入则丢失 。
这并不只是理论上的罕见场景 , 而是很容易在现实工作的负荷或驱动器断电故障中复现 。
对于要求保证更高数据完整性的应用程序 , Mac OS X 提供了 F_FULLFSYNC 这一 fcntl 命令 。 F_FULLFSYNC 要求驱动器冲刷所有缓冲区数据 , 写入永久存储 。
[ 节选翻译;粗体均为笔者所加 ]
换言之 , 在 macOS 下 , fsync并不会冲刷缓冲区 。 要实现与 Linux 下相同的效果 , 应该使用另一个函数 fcntl , 并附加 F_FULLFSYNC作为命令参数 。
事实上 , 促使 Martin 开展这项测试的疑问——内置硬盘在 macOS 和 Linux 下性能差距巨大 , 其原因正在于此 。 如果对于同一项操作 , Linux 因为 fsync的要求「送货上门」 , 而 macOS 却耍滑头地送到驿站就点了送达 , 那么两者的效率当然不能同日而语 。
Martin 由此得出的观点是:如果一直「岁月静好」 , Mac 内置硬盘确实速度令人望其项背 。 但一旦发生断电的意外事故 , 它就比第三方硬盘有更大风险遭遇数据丢失 , 对于没有电池作为后备供电的桌面型 Mac 就更是如此 。

特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。