背景
跟食品一样,代码也有过期时间。但糟糕的是,食品出产时就已标明了何时过期,但是一段代码是否过期却不好判定。
我们通常有这样的经验,当一个资源地址(url)要下线时,我们会从 nginx 的请求日志里查看该接口在最近一段时间内有没有被访问。
函数也可以做类似的处理,要解决的问题是,由谁来充当 nginx 记录请求的角色。
现状
当前网络上已经有比较好的支持,最典型的实现有以下几类:
- python 用来性能调优的库,如 profile、hotshot 等
- 使用装饰器实现,每个要统计的对象都需要加装饰器,操作不够优雅且略笨拙
- 自己维护变量统计,这种人工成本较大
方案 2、3 成本都比较高,且实现不够优雅,难以在高层次上复用。
方案 1 是比较好的一种方式,但也存在着它的问题。
对于脚本来说,这种方式很具优势。但是,对于大型系统来说,这类库的接入成本不低,可操作性较差。
其次它的抽象程度不够,需要自己再做额外分析处理,很难做到开箱即用。
设想
基于以上原因,我们可以设想一种更为友好的方式,以一种系统的抽象粒度给出。
这里有一个很重要的指标需要评估,就是对系统性能的影响有多大。当然,这是个技术问题,可以从技术角度解决。
我们这里使用着色来形象地表达记录访问状态的动作。不考虑性能影响,我们的目标是可以针对某命名空间下的对象及其方法进行着色,并获得着色后的可视化效果,以辅助对旧的代码进行重构。
我们希望有一个开关来控制着色,并可以热启动和热停止,且停止后尽可能减少或彻底取消对性能的影响。
着色器记录的信息,包括函数的调用次数及耗时。我们希望可以对各层级进行比较,可以很简单地看出对象下哪个函数在近一个月没有调用过,或者一个函数调用的平均耗时。
更上一层次,我们希望该功能以一种成熟的第三方模块给出,仅需配置极少内容即可使用。如作为 django 的第三方模块。
实现细节
我们将使用钩子或其它技术手段,接管函数的调用逻辑。我们将记录函数的如下信息:
梯度时间 | 函数或属性 | 调用次数 | 平均耗时 |
---|---|---|---|
2020-03-28 20:01 | views.WelcomeView.get() | 20 | 0.2 |
2020-03-28 20:01 | views.WelcomeView.post() | 3 | 0.5 |
2020-03-28 20:01 | views.WelcomeView.var | 2 | 0.5 |
由于请求量较大,可对数据做缓存处理,并定期刷新到数据库;由于数据量较大,可对过旧的数据进行压缩处理。
系统将对该数据制作报表,报表主要有两种:
第一种,一段时间内函数的调用次数热力图,并对不同函数按调用次数作升序排列。
第二种,一段时间内函数的调用耗时热力图,并对不同函数按调用平均耗时作降序排列。