LRU 和 SIP#

---
创建日期: 2020-03-17
---
两件不太相关的事情,闲谈。

LRU#

写了脚本映射IMC的采集项目(文件夹结构),可以获取任意时间段内的数据而不关心在哪个目录中。 也是为了数据池特性做准备。

运行倒是没什么问题,就是太慢了。 每次读取一个文件,然后截取其中一部分,再跑到另一个文件下面读取截取。

往往一个长的文件里又有许多可截取的片段,那么同一个文件在第二步的时候又得重新读取一遍(因为第一步完成后就释放了)。 所以这个过程花费了很多时间重复读取。(当然也有很多次在读取采集文件的信息头)

需要缓存,管理缓存又很麻烦。难道要开个服务程序、甚至是架个服务器? 我只是想利用本地的内存,而且也算临时的,和程序本身同生命周期。 Python有很优雅的解决方案。装饰器functools.lru_cache,完美诠释什么是Pythonic。(好吧,我不知道)

确实很简单,而且定义一个包装函数(wrapper),还不会影响原来的程序。 只不过使用了默认的参数(maxsize=128),好像没什么提升,内存也很稳定。 心虚着使用了maxsize=None,果然内存蹭蹭地往上涨,还好没超限。速度也提升了许多,明显看到没有重复加载文件。 这个时候再看cache_info,显示currsize=1246,就才几个通道啊,访问次数都4万多次。

事后算算,31个文件夹和30个通道,假设对应时间节点的文件夹平均在遍历了一半的时候找到,也是465个文件访问。 如果再算上信息头,因为只包含信息头,参数不同,那么就是翻倍了。

再对比了几次,maxsize=512的时候hits=0,而maxsize=1024就比较成功了,和maxsize=None基本一致。 所以果然是和次数有关系,是我低估了访问的次数。None的内存只升不降,1024的那个还有下降的时候,因为次数到达了,前面的大文件被清除了。

实际上理解的顺序并非如此,我纠结了很久maxsize到底是次数还是大小,为什么官方提供的没有大小的,没人有大小的需求吗? 对数据池特性,大小还是很重要的,采集文件大小不受控。次数少,缓存不起作用;次数多,不小心内存爆了。 找到了一个脚本能够设定内存剩余的空间。

缓存的作用,比如处理了一些数据后,也可以缓存起来,不过要把参数可哈希化。 比如加速数据,处理方法、齿轮箱、处理参数等等哈希化,就可以缓存起来。(当然数量太多就另当别论了) 还有处理过的列表、时域数据可视化(这个不是主题吗?)。

SIP#

另一件事是“SIP”。 实在受够了在不同的Python发行版间切换,公司安装的、自己WinPython解压的(两个)。 一直用旧版本的主要是代码依赖PyQt4,而公司的版本没有。 直到需要比较新的库引入的改进。

切换到PyQt5的过程会挺漫长的。 突然意识到,为什么不装个PyQt4呢?于是就去下whl的包。

安装失败,安装成功后运行失败,在用户空间和主空间来来回回测试了多轮。

原来:

  1. 安装失败是因为有些程序打开着,SIP运行中,没有被替换掉

  2. PyQt还有SIP版本依赖,而且还是区间依赖,而不是向下兼容的方案

  3. SIP的问题不会直接报错,而是选择了默不作声的“kernel die”

那在同一个发行版中,能否二者共存?总不要我为了用一个卸载另一个吧! 结果是可以的,在这里描述。(也依然很奇怪的,没怎么搜到这种需求)

一如既往,虽是轻描淡写,安装卸载反反复复操作了好多次。

以前不知道SIP是什么,恰好前几天看的Python的C/C++代码绑定,所以大概知道用于编译的。 把C/C++代码转化为Python可用的模块,这个转换过程(甚至是执行过程)就需要SIP。 用ctypes得可能没有代码提示,用Python重写,估计得累死。