为什么 Steam 删除 80G 的游戏只用了一秒?

这个问题下截止到目前的回答还没看到一个特别准确的。

既然是80G的Steam游戏,默认操作系统是Windows,文件系统是NTFS。Windows支持的其它文件系统,FAT/FAT32分区最大只有8G/32G(理论上FAT32分区大小可以是2T,但Windows不允许用FAT32格式化大于32G的分区),放不下80G的游戏,exFAT默认只能用来格式化移动存储设备不能用来格式化固定磁盘,所以这个问题下用FAT来解释的回答大概率都是错的。ReFS估计没几个人在用吧?

在NTFS分区里面,一个文件,根据文件大小的不同,有3处或者5处相关的信息:

  1. 在$MFT里面的FILE记录,大小固定为1K。$MFT(Master File Table,主文件表)是NTFS最重要的文件,默认隐藏不能访问,记录着这个分区内所有的目录和文件信息。一个文件在$MFT里面的记录主要记录了文件名、所在文件夹的记录号、大小、创建/上次修改/上次修改$MFT记录/上次访问时间等属性。如果这条1K记录剩余的空间大于文件大小,使用一个特殊的属性直接在记录中保存文件的数据,这个属性在NTFS称为常驻属性;如果剩余空间小于文件大小,文件数据需要使用额外的簇保存,使用另一种属性记录这个保存这个文件数据所占用的簇,这个属性称为非常驻属性。
  2. 在上级文件夹的索引数据中的记录,大小不定,通常在88~600字节之间。每个文件夹(包括根目录)在内,会记录本文件夹下所有子文件夹、文件的信息,包括文件在$MFT里面的记录号、大小、创建/上次修改/上次修改$MFT记录/上次访问时间等属性,这些信息占用82字节。此外还有这个文件/子文件夹的文件名,最大255个字符,每个字符占使用unicode编码,占两个字节。最后会补齐8个字节。此外,为了兼容DOS的8.3文件名,每个文件/子文件夹通常会有另一条文件名是8.3格式的记录,这条记录的大小一般不会大于96字节。
  3. 在$Secure里面的记录,数量和大小不定。$Secure记录每个文件的权限,例如某个用户/组对这个文件具有什么样的权限。对于家用情况,没多少用户/组,一个文件的权限数据通常很小不会超过4K。
  4. 在$Bitmap中对应的位。NTFS分区中每一簇按顺序对应$Bitmap文件中的1bit,0表示这一簇未被占用,1表示被占用。如果是文件在$MFT记录中的数据属性为非常驻属性,文件所占用的每一簇在$Bitmap文件中对应的bit置1。
  5. 文件数据实际占用的簇。一般来说稍微大一点的文件,都很可能会形成多个碎片,但这个问题是删除文件,无需考虑碎片的情况,这个后面会提到。

根据第1项的说明,如果文件夹数据/文件大小很小的话,上面4、5两项是没有的。如果是簇大小为4K的NTFS分区,80G的文件在$bitmap中占用80×1024×1024÷4=20Mbit=2.5MB。如果考虑到这些簇可能散乱分布在整个分区中的不同位置,需要把整个$Bitmap文件更新一遍的话,一个1TB的分区的$Bitmap文件是32MB。

所以,每删除一个文件/文件夹,都要更新1~4项的信息。第5项无需更新,文件所使用的簇在$Bitmap中对应的位置0后,将来如果这些簇用来保存新的文件数据会直接覆盖。当然,如果是使用固态硬盘的话,Windows会发送trim指令给固态的主控,主控会在空闲的时候根据磨损算法回收对应的Page。

如果是机械硬盘的话,在没有缓存的前提下,单是找到1~3项的记录通常就需要十多次寻道。每一处记录的更新必然有一次寻道,但对于固态来说只要文件数量不是太多,这个寻道(固态其实应该叫寻址更合适点)时间都可以在1秒内完成。而每一处信息更新通常只需要写入1簇(4K)的数据,就算是机械硬盘,这个数据传输时间也是基本可以忽略的,固态就更不用说了。

最后,根据前面的论述,如果一个游戏有1024个文件的话,写入数据量是1024×12KB=12MB,加上$Bitmap文件的2.5~32MB,总计是14.5MB~44MB。SATA固态硬盘通常4K随机读性能在20MB/s以上,4K写性能100MB/s以上,在这些数据都在缓存中的前提下,还是可以在1秒内完成的。如果文件数量更少,就更加没有压力了。


某些回答里面猜测的这些索引记录是否会在Steam安装游戏的时候使用预分配空间是使得这些记录集中在一起,我可以肯定不是。下图中灰色底色的行是我电脑上的Steam里面泰坦之旅这个游戏的文件夹以及文件夹下若干个文件的起始簇编号、扇区地址:

可以看到,这几个文件/文件夹不管是$MFT记录号还是簇编号,都并不连续。另外,这个游戏的文件加上目录数量不超过600。

Steam能做的,估计是把这些记录所在的扇区缓存到内存中,减少读取数据的寻道/寻址次数。毕竟前面的计算已经足以说明,就算几个游戏加起来如果有一千个文件,这些数据加起来也就12MB,一万个也就120MB(不算$Bitmap),对于今天的主流配置来说这点内存占用完全可以忽略。而不管是删除游戏还是我们平时打开游戏来玩,就不需要从硬盘中读取这些数据了。


最后,关于NTFS分区上如何找到一个文件的$MFT记录号、上级文件夹的索引数据,有兴趣的朋友可以看看我前几天写的文章:

木头龙:为什么说固态硬盘的4K性能很重要?

来源:知乎 www.zhihu.com

作者:木头龙

【知乎日报】千万用户的选择,做朋友圈里的新鲜事分享大牛。
点击下载

此问题还有 120 个回答,查看全部。
延伸阅读:
请问steam中哪些游戏是23块钱以内的而且好玩?

哪些游戏是没必要玩前作的?