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的包。
安装失败,安装成功后运行失败,在用户空间和主空间来来回回测试了多轮。
原来:
安装失败是因为有些程序打开着,SIP运行中,没有被替换掉
PyQt还有SIP版本依赖,而且还是区间依赖,而不是向下兼容的方案
SIP的问题不会直接报错,而是选择了默不作声的“kernel die”
那在同一个发行版中,能否二者共存?总不要我为了用一个卸载另一个吧! 结果是可以的,在这里描述。(也依然很奇怪的,没怎么搜到这种需求)
一如既往,虽是轻描淡写,安装卸载反反复复操作了好多次。
以前不知道SIP是什么,恰好前几天看的Python的C/C++代码绑定,所以大概知道用于编译的。 把C/C++代码转化为Python可用的模块,这个转换过程(甚至是执行过程)就需要SIP。 用ctypes得可能没有代码提示,用Python重写,估计得累死。