突破性能CI

什么是性能CI

性能CI可简单定义为CI(Continuous Integration)集成性能测试用例。主要用于监控系统运算速度、存储容量或网络I/O是否满足系统设置指标,而非发现故障。

性能测试通常包括:负载测试(Load Test)、压力测试(Stress Test)、容量测试(Volume Test)、峰值测试(Spike Test)等非功能型测试。


性能CI的价值

一方面,Donald Knuth告诉我们“过早的优化是万恶之源”,

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. - Computer Programming as an Art(1974) P671.

当然,我并无意挑起性能狂人与设计大师们的战争,但凡有些性能优化经验的同学定能理解其中要义,过早的优化至少会带来如下问题:

  • 忽略整体设计
  • 陷入局部优化
  • 破坏可读性
  • 增加偶发复杂度

另一方面,对于遗留系统,发现性能问题往往为时已晚。会带来:

  • 定位成本高
  • 优化难度大
  • 波及影响多
  • 测试成本高

所以,我们期望做到:

  1. 开发人员专注于设计、编码
  2. 提交代码出现性能问题及时告警
  3. 可视化性能数据,并可链接到劣化代码
  4. 提供定位信息协助分析

性能CI面临的主要问题

  1. 性能用例的有效性不高

    简言之,监控的场景不能包含性能劣化路径。表现为内场表现良好,外场表现糟糕;局部性能良好,系统性能糟糕。

  2. 性能用例部署、执行时间较长

    CI要求更早、更快的反馈。性能测试受制于物理环境、仪表资源、采样周期等限制,通常自动化部署困难,用例执行时间长。

  3. 性能测试数据的稳定性

    判决让人信服的前提是准确。由于不同的构建机器、不同的部署环境、不同的用例配置、不同组件间的干扰、性能指示器数据的波动等原因,性能测试数据出很大波动性,导致难以判决劣化是由于合入代码还是波动所致。

  4. 自动化准确识别劣化点

    劣化阈值设置过大可能漏掉某些劣化点,设置过小可能产生误报,准确识别劣化点困难。另外,由于诸多约束,很多判断需要人为干预,完全自动化较困难。

解决思路与方法

通过对性能CI面临主要问题的分析,核心要解决有效性、高效性、稳定性、扩展性四方面的问题。

  1. 提高性能测试用例的有效性
  • 业务价值驱动,识别劣化路径

    “程序的性能特质倾向高度的非直觉性”,性能优化靠猜是极其不告谱的。性能劣化路径的识别亦如此,我们需要根据系统在真实部署环境的业务场景,选择用例,确定用例部署优先级。

  • 解耦系统内不同组件间的干扰

    在一定程度上,可以对复杂系统的各个组件的性能分开验证,可以考虑牺牲一些不关注组件的真实性,换取关注组件的稳定性。

  • 自动准确识别性能劣化点并分级告警

    自动准确的识别劣化点,是判定性能CI是否有效的关键指标。需要动态找到某个阈值作为置信区间,我们可以参考异常检测方法。常见的异常检测方法有:极值分析,概率统计建模,线性回归模型,信息论模型,高维孤立点检测等。下面介绍一种实测中比较有效实时告警的方法:

    Mean(N) ± SD(N),其中N表示样本容量,Mean表示平均值,SD表示标准差。样本容量选取过去一段时间产生的样本,不能选取过去的所有样本,否则置信区间无法收敛。

    分级告警是指可以定义实时告警、触顶告警等不同级别告警。

    • 实时告警:以过去一段时间的样本作为实时告警模型的输入并生成置信区间,当前数据超出该区间则告警。
    • 触顶告警:以某个初始基准值作为参考,设置可以容忍的最大劣化/优化阈值并生成置信区间,当前数据超出该区间则告警。触顶告警一般用于实时告警无法捕捉到的、缓慢增加的劣化的场景,触顶告警一旦触发,预示需要启动专项优化了。
  1. 提高性能测试用例的高效性
  • 测试用例分级部署

    分级部署是指将性能测试用例分级部署在单元测试,集成测试,系统测试等不同阶段。用例间相互补充,可以更高效的利用测试资源,减少用例执行时间。

  • 测试用例并行部署

    如果测试用例部署环境充足,考虑并行部署用例,可以大大缩短用例执行时间,简化用例部署场景。

  • 不同构建按不同粒度监控

    如果做不到用户每次提交在给定的时间窗内给出执行结果,可以考虑将多次提交打包成一次构建执行,出现告警后打包提交逐单回退验证(需要部署镜像环境用于回退单验证)。

  • 寻求慢速性能指标的替代指标

    如果在用性能指示器的采样周期较长,在不影响稳定性的前提下,考虑寻求其他更快速性能指标进行替换。性能指标包括:CPU Utilization,Latency,IPC(Or CPI),Cycles,Instructions,CacheMiss.

  1. 提高性能测试数据的稳定性
  • 部分模拟环境代替真实物理环境

    真实物理环境相对于模拟环境更脆弱,更不易控制,在分级部署原则的指导下,对于不关注组件,可是考虑使用模拟环境代替真实物理环境。

  • 增加系统内其他组件的稳定性

    复杂系统是由多个组件组成,系统性能表现为它们共同作用的结果,通过打桩等手段,提高不关注组件的稳定性,有利于提高被监控组件的稳定性。

  • 增大样本容量(冗余)

    冗余是提高稳定性最常用的方法,挑战在于在样本量增加情况下,如何不增加执行时间。推荐使用Latency,IPC等指标代替CPU使用率。

  • 多维度样本参照(相关性)

    具有相关性、不同维度的性能数据相互参照,提高判定的准确性。

  • 寻求波动性能指标替代指标

    系统性越强的性能指示器(例如CPU使用率)波动性越大,考虑使用一些可被拆分、组合的指示器(例如函数时延,Cycles等)替代。

  1. 提高性能用例的扩展性
  • 抽象出框架与API接口
    良好的扩展性基于对操作的抽象、良好的分层、稳定的API接口,性能CI对日志数据的操作可以抽象为数据采集、数据处理、数据持久化、数据可视化四层,每层定义清晰的API接口,性能用例仅需要新增配置即可。

  • 工作环境与测试环境分离
    工作环境负责及时反馈性能劣化点,镜像环境负责对劣化点优化的验证,二者并行工作



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章