好吧,我的标题越来越土了,本来想取个“XX之迷”或者“走进科学”啥的,不过其实是个小问题。总之,最近我在用 matlab 跑一些实验的时候,保存的结果比较大,其实也不算太大,就几百兆,但是由于有很多个这样的文件,所以占用空间还是比较大的,而且几百兆的 .mat 文件每次 load 进来画个图之类的也要等半天,非常不方便。于是我就想能不能有方法处理一下。
一开始我以为是因为我存储的数据里有一些位图,所以才会比较大,于是我写了一个工具来将位图压缩了一下,发现单张图片即使是无损 JPEG 压缩也可以变得比原来小很多,于是赶紧用来处理原来存储的文件,结果发现处理之后基本上没有任何改观。由于很久没有遇到这么神奇的“bug”了,我比较兴奋,把代码相关的地方都检查了一遍,发现其中有一个中间计算结果作为 cache 放在一个 struct 的 field 里,而这个 cache 理论上是可以丢掉的(虽然要再算一遍很耗时,但是基本上不会再重跑这个实验了),于是我果断把它咔嚓掉。再一运行,保存……结果发现居然一丁点改观都没有!
更为诡异地是,我用 whos 看 matlab 里那个 struct 占用的空间,得到的结果其实是很小,但是当我 save 它到文件的时候,它就莫名其妙地占用了大量空间。 -.-bb 我用一个赶紧的 matlab workspace 把这个文件加载进来,逐一删掉其中的变量做测试。
其实一开始我也比较怀疑其中的一个 function_handle 的 field ,我在想不会 matlab 聪明到为了保证 function handle 下次加载进来能够运行,把所有相关的代码和引用到的代码也一应打包了吧?-.-bb 但是 Matlab 的文档说得很清楚就是在其他地方 load function handle 的时候,如果原来的代码文件不存在或者被修改过的话,就会发生 unexpected 结果。但是呢,当我删去 struct 的那个 function handle 的时候,竟然真的就瞬间从几百兆变成几兆了。
虽然是大跌眼镜,但是我突然一下子又想明白了。原来那个 function handle 里引用了之前计算的那个 cache ,使其变成了一个 closure ,结果呢,这个 cache 就成了无法访问到的幽灵数据,看不见摸不着,但是却占据这空间,matlab 在保存的时候也把它一起保存了,结果就如此了!
鉴定结果:closure 这样的语言特性,即使不是神级别的也是幽灵级别的,其实我当初尝试在写 irobot2 的时候用 closure 来在 Python 里实现完全只读访问的成员变量的时候,就应该意识到这个问题了。看来,世界上最远的距离,不是 YQ 和 ZJG 之间的距离,而是我就藏在你的 closure 里…… :p
very good, 我最近也遇到你这个问题:数据量太大,保存了几个G的mat数据,但是缺少你这样的究根问底的精神啊,就那么放着了,呵呵
学习了