小众消息的冯大辉前两天推送了一篇很有意思的文章,大概是探讨一个B站视频对微信存储机制可能存在的误解。文中提出了一个实验方法,看到做了试验可能会有奖品,我眼睛一下放光,不如就趁此机会做几个试验,好好探讨一下微信在iOS上的文件存储机制,包括:
- 转发文件是否会占用额外的存储空间?
- 从同一人处多次接收同一份文件是否会占用额外的空间?
- 从不同人处多次接收同一份文件是否会占用额外的空间?
- 微信和WeChat在以上这些问题上是否存在差异?
- 同一台手机上的不同微信账号接收的同一文件是否占用额外存储空间?
试验的环境是iOS 14.8.1、iPhone 11、微信8.0.28。首先我们删除手机上的微信重新安装。登录一个WeChat小号(小号A)。此时微信占用的空间是少的可怜的752.2MB,其中数据占244.5MB。我提前准备好了一个Ubuntu的iso镜像(880MB)。将它发送给这个小号。下载后重启手机,可以看到,微信占用的空间变成了1.77GB,其中数据占1.26GB。多出来大约1GB的空间,可能是除了文件以外的缓存、其他需要的程序和资源文件。
接下来我们正式开始实验。我们讲接收到的文件转发给三个不同的小号。重启手机,可以看到,如冯大辉所料,微信所占用的存储空间并没有增加。依然是1.77GB(数据1.26GB)。微信显然做了最基本的文件存储去重。
接下来,我从另一个微信号将刚刚发送的文件再次转发给小号三遍。当我点进新发送的文件时,看到需要接受文件,我有一种不详的预感。难道微信真会重新接收一遍文件?所幸,当我点击接收文件后,文件在一瞬间就接收完成了。显然,微信也伴有服务器端的去重,在服务器上的同一份文件,在本地并不会接收多次。重启手机也可以看到,微信占用的空间并无增加。
按照这个逻辑,即使是不同的人转发给我的同一份文件,应该也不会需要重复下载,或是占用额外的空间。我试着用另外两个小号(小号B、小号C)将同一份文件转发给小号A。虽然也显示需要接收文件,但同刚才一样,一瞬间就完成了接收。再次重启手机,微信所占用的空间依旧没有变化。
不过,刚才验证的情况中,虽然是多个账号转发给一个小号,但是微信很容易在服务器端追溯到,这些文件的源头是同一个。那假如各个账号是各自上传的同一份文件,微信在服务器端是否也有去重能力呢?为此,我在另一台小米手机上登录小号B与小号C,各自发送同一份文件给小号A。发送文件的时间较长。这似乎足以让人判断出,微信大概没有类似百度网盘的文件去重判断。
然而出人意料的是,小号A还是一瞬间就完成了文件的接收。重启手机后也可以看到,微信所占用的空间并没有明显增加(总计1.83GB,数据1.32GB)。这说明至少在服务器端,微信确实能够判断出一份文件是否曾经上传过。而缺少类似网盘的秒传功能,可能是微信本身没有相关功能,也可能是Android端微信需要优化。
出于好奇,我又尝试从小号B发送一份内容相同,只有文件名不同的文件,看看微信的查重是否基于文件名,或是基于文件本身。经过等待漫长的发送,如我所料,接收只在一瞬间就完成了。由此可知,微信的文件去重基于内容,并不依赖名字。
上面测试的都是同一账号下的情况。那么,同一台手机上的不同账号间又是怎样呢?我尝试在刚刚登录小号A的手机上切换了一个微信账号B。可以看到,这次转发收到的相同文件,需要重新接收下载。重启手机也能看到微信的占用空间变为3.8G(数据3.29G)。不过在这一微信账号下,同一文件仍然只需要下载保存一份,再次收到就能秒存。同时利用这个微信账号简单试了一下,我发现以上WeChat的文件存储机制对微信也同样成立。
到这里,我们可以基本得出结论,iOS的微信文件存储去重做得还是比较令人满意的。同一账号下的同一个文件,只要内容相同,就只会在本地留存一份。未来微信团队可以努力的方向是不同账号间的文件存储去重。
另外值得一提的是,微信大概是真的有在代码层面实现去重,而非依赖APFS的CoW特性。因为即使只占一份空间,iPhone在统计容量时也会重复计算一个文件的多次拷贝。通过多次复制粘贴同一份文件,你能很容易地复现苹果的这个Bug:
在我原本的设想中,我写出这篇文章后,与其拿到那500元钱,我更想获得一个与Fenng交流的机会,说服他微信是一个糟糕的产品。但转念一下,即使我做到了,也并不能改变得了微信这个产品本身,以及我们必须使用它的环境。更何况再一看那篇文章,是要证明微信没有去重才能拿到那笔钱。是我审题不细了😀
如果你觉得我的这篇文章不错,也欢迎你阅读我之前有关微信的两篇文章:虎头蛇尾的《微信戒断实验》与尝试减少微信占用空间的《微微微信怎么办》。