Uperf是一个Android用户态性能控制器😉
用户态性能控制器:俗称“调度”。是一个在Android操作系统中用于管理和控制设备性能的工具。它会在应用程序和系统服务在运行时调整设备的性能参数,以优化用户体验和响应速度。运行在用户态(Userspace)也意味着它不属于内核空间,而是作为普通的应用程序或服务运行。这使得性能控制器能够更灵活地响应各种性能需求,且具有泛用性,而无需修改或重新编译内核。
处理器功耗模型
这是通过实验精准测试的数据建立的功耗模型,在调度中起到了决定性的作用,我们可以微调功耗模型,使某个集群的调度偏激进或者保守,达到我们希望的效果。
efficiency(相对性能):该集群cpu单核相对于A531.0Ghz的同频性能。用以计算该集群能耗比。
typicalPower(基准功耗):决定了核心集群的趋向,基准功耗越高,调度相对保守。
typicalFreq(基准频率):绑定基准功耗的频率。调低会使调度认为该集群能耗比差,不应大幅调整。或者两者一起修改。
sweetFreq(甜点频率):需要升到的频率越高,延迟越大。甜点频率以下的升频不受到升频延迟的影响。
planFreq(目标频率):非重负载升频首先选择的目标频率。
freeFreq(自由频率):即集群可以达到的最低频。
单位都是Ghz。
CPU调频参数相关
baseSampleTime/baseSlackTime(采样周期):按此周期采样CPU频率。后者在cpu空载时生效。减少也许会减少本就微不足道的轮询花销,也会减慢突发负载时cpu的反映速度。
latencytime(升频最小延迟):从低性能集群最低频 到 最高性能集群最高频率 的最小延迟。0~10.0
slowLimitPower(长期功耗限制):顾名思义。
fastLimitPower(短期功耗限制):可以理解为限制的峰值功耗,超过长期功耗限制的部分会消耗缓冲池,消耗完毕后恢复slowLimitPower长期功耗限制。
fastLimitCapacity(短期功耗限制容量):应当是和上面的短期功耗限制协同作用。yc给出的是个不标准的单位瓦秒。我举个例子说明:假设容量是20,那么功耗超过了长期功耗达到了短期功耗,那么就会容量就会减少直到为0。cpu被迫降频到长期功耗水平。0~999.0
fastLimitRecoverScale(短期功耗限制容量恢复缩放因子):能耗低于slowLimitPower时,能耗缓冲池余量根据缩放因子恢复,直到功耗限制容量fastLimitCapacity。0.1~10.0
PredictThd(分支预测阈值):如果CPU集群最大负载增加量大于此阈值,集群调频使用预测的负载值并忽略latencyTime。0~1.0
margin(性能余量):顾名思义。
burst(额外的性能余量):忽略升频最小延迟latencyTime与功耗限制。适合用于处理突发的、短暂的负载高峰。
guideCap(启用引导EAS任务调度负载转移):根据能耗模型引导EAS调度器放置任务。
limitEffciency(整体能耗限制):低性能集群最大频点能效值不高于高性能集群当前频点的能耗值。大意是通过功耗模型计算功耗,适时把任务交由大核处理达到更好的能效。
根据性能负载计算性能需求, 需求=负载+(1-负载)* (性能余量margin+额外性能余量burst) ,那么这个公式有什么含义呢?
这个公式基于负载 load 来计算所需的性能需求 demand。load 是当前的负载值,margin 是一个额外的性能余量,通过 (1 - load) 这个因子,其实际上是在调整 margin 和 burst 的权重。在负载较低时,预留更多的性能余量保证流畅,而在负载较高时进一步限制余量。这一机制的考虑是基于cpu频率与功耗的非线性增长,且正常情况下的高负载持续时间普遍不长。所以在低频低负载的时候预留更多余量,高频时限制余量减少额外的功耗。介绍完这个基于负载预测和当前负载来计算性能需求的机制,我们再引入PredictThd 来使用这个公式。CPU集群最大负载增加量大于PredictThd后,直接使用PredictThd代替预测负载load,为性能需求demand设定了一个上限,又设置了一个忽略latencyTime的特性,使cpu可以直接达到被设定的demand,尽可能减少使用中感知到的卡顿。 以上内容可以使用分洪水闸理解,本质上是需要使洪水(突发负载)最快流过具有高度惩罚的闸口(CPU功耗的非线性增长)。我们需要选择最合适的高度,在 高度惩罚 与 使水最快流过 两者间取得平衡点。
功能模块的参数预设段
在这里定义不同模式(如powersave,balance等)。每组参数预设必须包含 idle, touch, trigger, gesture, junk, switch,如下样例所示。
"balance": {
"*": {
},
"idle": {
},
"touch": {
},
"trigger": {
},
"gesture": {
},
"junk": {
},
"switch": {
}
}
参数值采用层叠样式表的设计方式,后方参数有更高优先级,会覆盖默认参数。 以下示例展示cpu.baseSampleTime的覆盖关系:
在 /initial/cpu 中定义 baseSampleTime 全局默认值为0.01
在 /presets/balance/ * 中定义 baseSampleTime 在该参数预设默认值为0.02,覆盖全局默认值0.01
在 /presets/balance/junk 中定义 baseSampleTime 在idle场景值为0.04,覆盖该参数预设默认值0.02
最后,在junk(掉帧)状态下的 baseSampleTime 为0.04。
"initials": {
"cpu": {
"baseSampleTime": 0.01,
}
},
"presets": {
"balance": {
"*": {
"cpu.baseSampleTime": 0.02
},
"junk": {
"cpu.baseSampleTime": 0.04
}
}
}
😊