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

[复制链接]
zxs1394 发表于 2023-9-14 18:30:49|来自:中国 | 显示全部楼层 |阅读模式
为什么 Steam 删除 80G 的游戏只用了一秒?
全部回复5 显示全部楼层
hellos 发表于 2023-9-14 18:31:41|来自:中国 | 显示全部楼层

图片来源网络
photoshoplxy 发表于 2023-9-14 18:32:27|来自:中国 | 显示全部楼层
卸游戏大伙已经给你解释清楚了,我不知道你有没有删过创意工坊啊。
如果你订阅了一堆mod,不卸载只是取消全部订阅,就会发现steam压根没删任何文件。
然后可能某一时间steam突然想起来,我草,忘了删文件了,才在你的下载界面弹出一个更新创意工坊内容。
红黑白蓝 发表于 2023-9-14 18:32:48|来自:中国 | 显示全部楼层
写入:房客入住房间。
删除:宣布房间为空,可以入住。
覆盖:让新房客进去把老房客捅死。
文件修复:法医缝缝补补把尸体补全。
分区:成立子酒店。
碎片文件:把新房客分成好多块散到各个房间。
写保护:把房间锁死。
格式化:纳粹认为酒店里全是犹太人,派出党卫军抓捕。
jsznet 发表于 2023-9-14 18:33:17|来自:中国 | 显示全部楼层
@pansz 提出了5个猜想:

  • steam其实在后台删除,只不过先告诉你删完了,实际上他还在后台继续做删除工作呢。
  • steam使用了类似windows回收站的机制,删除的瞬间直接把游戏移动到steam内部的私有回收站,这样的操作就必定极快,给用户造成了秒删除的感觉。
  • 前两者结合,先移动到私有回收站让你看起来游戏已经没了,然后在后台继续做删除工作。steam的空间预分配,或许本质上就是它的私有回收站。
  • 题主的硬盘真的就那么快,80G确实可以秒删,现在的高速NVME结合操作系统缓存或许真能做到。
  • 可能还有其它可能,但具体情况要具体分析。
<hr/>
我用Process Monitor 监控了一下:
动作:用steam卸载dota2
效果:经过三十秒钟之后,steam表示卸载完成
环境:Win10系统,固态硬盘
procmon表示:
从 2021/8/6 11:47:51.6472076 到 2021/8/6 11:48:30.1125172 这半分多钟的时间里,steam.exe反复对C:\Program Files (x86)\Steam\steamapps\common\dota 2 beta\里的文件调用 CreateFile QueryAttributeTagFile CloseFile 这三个操作。(也就是删除操作)
所以,我提出一个新的猜想:

  • steam就是老老实实的做删除的。
  • 题主提到的那个80G的游戏才是重点,是否那个游戏自身做了固实存储?(请题主告诉大家那个游戏的名字
<hr/>更新:评论区有人说steam删了游戏立刻重新安装是秒安。我实验了一下,不是秒安,是重新下载。
zpgzs 发表于 2023-9-14 18:33:47|来自:中国 | 显示全部楼层
这个问题下截止到目前的回答还没看到一个特别准确的。

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

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

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

根据第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秒内完成的。如果文件数量更少,就更加没有压力了。
<hr/>某些回答里面猜测的这些索引记录是否会在Steam安装游戏的时候使用预分配空间是使得这些记录集中在一起,我可以肯定不是。下图中灰色底色的行是我电脑上的Steam里面泰坦之旅这个游戏的文件夹以及文件夹下若干个文件的起始簇编号、扇区地址:


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



Steam能做的,估计是把这些记录所在的扇区缓存到内存中,减少读取数据的寻道/寻址次数。毕竟前面的计算已经足以说明,就算几个游戏加起来如果有一千个文件,这些数据加起来也就12MB,一万个也就120MB(不算$Bitmap),对于今天的主流配置来说这点内存占用完全可以忽略。而不管是删除游戏还是我们平时打开游戏来玩,就不需要从硬盘中读取这些数据了。
<hr/>最后,关于NTFS分区上如何找到一个文件的$MFT记录号、上级文件夹的索引数据,有兴趣的朋友可以看看我前几天写的文章:
木头龙:为什么说固态硬盘的4K性能很重要?

快速回帖

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则