[Power/Heat] 20.9版本的电源管理是怎么回事,性能模式的代码写的什么鬼!??
Tofloor
poster avatar
DebuggerX
deepin
2023-04-28 22:06
Author

起因

我给自己写了个在手机上监控系统性能的app,可以随时方便地看到电脑当前的各种信息,界面长这样的:

image.png

图中处理器的指示器,以及中间每个核心的指示器,内部的圆环表示当前CPU/核心的工作频率,外圈表示利用率,这样我就可以在工作时,尤其是编译代码的时候,清楚知道CPU有没有拖后腿。

然后上周更新了20.9之后,发现在使用我一直使用的平衡性能模式下,性能监控显示的却是下面的样子:

image.png

可以看到,虽然是在空载状态,每个核心明明占用率都极低,却都运行在最高频率,这显然是不正常的。

于是在使用如下代码监控了cpu的性能模式:

watch -n 1 'cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor'

然后在控制中心的电源管理中,来回切换性能模式,结果发现果然当选择的是 平衡模式时,CPU实际运行的确实 性能模式(performance)

但是上周和本周前两天在优先解决另外一个更影响我使用的问题:[经验分享] 分享让用户可以自己强制指定系统缩放的方法,所以只能先搁置,直到昨天终于有空开始调查原因。

调查

我首先是去Github看了https://github.com/linuxdeepin/dde-daemon/tree/master/system/power1相关的代码,看了半天虽然感觉有些地方的逻辑也有点奇怪,但是没发现明显会导致我现在这种情况的代码。

然后又看了 /var/log/daemon.log 里的日志,发现4月17(没更新前)的日志是这样的:

2023-04-17 20:12:01 debuggerx-e5 daemon/system/power[1178]:  power_key_edit.go:110:  getDsgData key :  BalanceCpuGovernor  , value :  ondemand
2023-04-17 20:12:01 debuggerx-e5 daemon/system/power[1178]:  manager.go:353:  init end. getSupportGovernors :  [conservative ondemand userspace powersave performance schedutil]  , m.balanceScalingGovernor :  ondemand

而4月18(更新后)的日志就变成了这样:

2023-04-18 09:22:14 debuggerx-e5 dde-system-daemon[1166]:   manager.go:386:  init end. m.balanceScalingGovernor :  performance
2023-04-18 09:22:14 debuggerx-e5 daemon/system/power[1166]:  manager.go:386:  init end. m.balanceScalingGovernor :  performance
2023-04-18 09:22:14 debuggerx-e5 dde-system-daemon[1166]:   manager.go:616: [doSetMode] Set Governor, balanceScalingGovernor :  performance
2023-04-18 09:22:14 debuggerx-e5 dde-system-daemon[1166]:   cpu_handler.go:322:  SetGovernor governor :  performance
2023-04-18 09:22:14 debuggerx-e5 daemon/system/power[1166]:  manager.go:616: [doSetMode] Set Governor, balanceScalingGovernor :  performance
2023-04-18 09:22:14 debuggerx-e5 daemon/system/power[1166]:  cpu_handler.go:322:  SetGovernor governor :  performance

然后根据日志里的代码行号去看源码,发现居然完全找不到对应的代码???

通过 dpkg -l | grep dde-daemon查询系统的 dde-daemon版本是 5.14.137 ,但是Github上没有这个版本,于是看的是最接近的5.14.129版本

于是只能把 /etc/apt/sources.listdeb-src的注释放开,然后用 apt source dde-daemon才下载到了正确的源码……

分析

拿到源码,直接根据上面的日志里给到的代码行号看,结果就看到了如下代码:

612 func (m *Manager) doSetMode(mode string) error { 
613         var err error 
614         switch mode { 
615         case "balance": 
616                 logger.Info("[doSetMode] Set Governor, balanceScalingGovernor : ", m.balanceScalingGovernor) 
617  
618                 m.setPropPowerSavingModeEnabled(false) 
619  
620                 err = m.doSetCpuGovernor(m.balanceScalingGovernor) 
621                 if err != nil { 
622                         logger.Warning(err) 
623                 }

可以看到设置为平衡模式时,实际是使用 m.balanceScalingGovernor这个变量的值来设置的,所以再看这个变量是怎么来的:

32 const ( 
 33         configManagerId                   = "org.desktopspec.ConfigManager" 
 34         _configHwSystem                   = "/usr/share/uos-hw-config" 
 35         configDefaultGovFilePattern       = `config-[0-9\.]+-.*-desktop` 
 36         configDefaultGovContentDDEPattern = `CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_(\w+)` 
 37         configDefaultGovContentPattern    = `CONFIG_CPU_FREQ_DEFAULT_GOV_(\w+)` 
 38 )

…………

319 func (m *Manager) refreshSystemPowerPerformance() { // 获取系统支持的性能模式 
    …………
338         re := regexp.MustCompile(configDefaultGovFilePattern) 
339         if result, err := utils.FindFileInDirRegexp("/boot/", re); err != nil { 
340                 logger.Warning(err) 
341         } else if len(result) > 0 { 
342                 re = regexp.MustCompile(configDefaultGovContentDDEPattern) 
343                 _, matches, err := utils.FindContentInFileRegexp(result[0], re) 
344                 if err != nil { 
345                         logger.Warning(err) 
346                         re = regexp.MustCompile(configDefaultGovContentPattern) 
347                         _, matches, err = utils.FindContentInFileRegexp(result[0], re) 
348                         if err != nil { 
349                                 logger.Warning(err) 
350                         } 
351                 } 
352                 if len(matches) > 1 { 
353                         m.balanceScalingGovernor = strings.ToLower(matches[1]) 
354                 } 
355         } 
356  
357         if m.balanceScalingGovernor == "" { 
358                 logger.Warning("can't find balance scaling governor use ondemand") 
359                 m.balanceScalingGovernor = "ondemand" 
360         }

说明下这段代码:

  1. 首先去 /boot/ 目录下去找config文件,这个文件是系统内核编译时的配置,取找到的第一个进项下一步,找不到的话将平衡模式的调度器设置为 ondemand
  2. 在config文件中找以 CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_ 开头的行,并把第一个找到的项目的后面的内容转小写设置为平衡模式的调度器,如果没找到进行下一步
  3. 在config文件中找以 CONFIG_CPU_FREQ_DEFAULT_GOV_ 开头的行,并把第一个找到的项目的后面的内容转小写设置为平衡模式的调度器找不到的话将平衡模式的调度器设置为 ondemand

而看下我当前的config文件的内容,没有任何以 CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_ 开头的行,以 CONFIG_CPU_FREQ_DEFAULT_GOV_ 开头的行则是下面的样子:

CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set

所以在根据上面的代码和分析,m.balanceScalingGovernor这个变量就会被设置为performance。。。
我试了下,只要把上面内容里的第一行和第二行换下位置,甚至不用放开注释,也不用修改成CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y,重启后我的平衡模式就可以正常设置成schedutil了!

质疑

虽然本人水平不高,对Linux系统以及开发顶多算一知半解,但是上面的这个代码是在是难以理解难以接受。

  1. 怎么会想到用config文件来判断呢?要知道用户可能会安装多个版本的内核,boot目录下就会存在多个config文件,粗暴地取第一个找到的文件显然会导致不确定的结果,更不要说这个文件本身也是可以随意修改的
  2. 除去往内核选项里随意加CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_XXX这样的选项是不是符合规范,单纯用正则匹配到的行来设置变量是不是有点过于不专业了?就像我的改法,只要把未解开设置也未设置值的选项移动到上面的位置,就可以影响代码的执行结果,实在是有点扯了吧?
  3. 为什么已经发布的版本,却在Github上找不到对应的源代码,那这还算是“开源项目”吗?要不是知道可以用 apt source 下载源码,我不知道还要自己瞎琢磨吓找多久;不光是这个版本的 dde-daemon,我之前找屏幕分辨率的问题时就发现了Github上找不到正确版本的startdde(系统版本5.9.70,开源版本则是5.9.64);另外还有上面代码里的utils.FindContentInFileRegexp方法,看上去来自https://github.com/linuxdeepin/go-lib/tree/master/utils,实际去找却根本找不到这个方法,也就是说下载到的这份代码在我机器上根本就编译不了,要不是这个问题还算简单,看代码猜猜逻辑就够了,否则不知道要花多少时间精力才能解决。

希望有知情的同学可以解释一下这是什么情况,上面的那些代码该不会还要进入到v23吧?

我用deepin已经差不多10年了,可以说感情很深很深了,但是如果之后还总是出现这样的问题,可能我也不得不放弃了吧……

Reply Favorite View the author
All Replies
1 / 2
To page
liwl
deepin
2023-04-28 22:11
#1

一个配置文件引发的血案

like

楼主找问题的思路,很值得学习

收藏了

Reply View the author
DebuggerX
deepin
2023-04-28 22:11
#2

image.png
rage

Reply View the author
DebuggerX
deepin
2023-04-28 22:13
#3
liwl

一个配置文件引发的血案

like

楼主找问题的思路,很值得学习

收藏了

本质和配置无关,明显是代码的问题

Reply View the author
感恩的心
deepin
2023-04-28 22:20
#4

实习生写的代码么

Reply View the author
BG7ZAG
deepin
2023-04-28 22:21
#5
DebuggerX

image.png
rage

反向优化?😂

确实像犯了低级错误,要不就是新手写的这段代码?👀

Reply View the author
DebuggerX
deepin
2023-04-28 22:24
#6
感恩的心

实习生写的代码么

就算实习生写的,难道没有Code Review吗?做系统这么严谨的东西,而且是影响性能续航表现这种相对重要的功能,这么随便就发布了?

这种代码给我review的话,我死都不会给过的

Reply View the author
DebuggerX
deepin
2023-04-28 22:25
#7
BG7ZAG

反向优化?😂

确实像犯了低级错误,要不就是新手写的这段代码?👀

我觉得不只是写代码的人的问题

Reply View the author
阿尼樱奈奈
Moderator
2023-04-28 22:30
#8

额,这个重大问题必须上报给官方

Reply View the author
longlong
deepin
Developer
2023-04-28 22:44
#9

这个我来详细解释下,我是发现这个性能模式问题的人,同时也给dde-daemon组提出这个问题:

怎么会想到用config文件来判断呢?要知道用户可能会安装多个版本的内核,boot目录下就会存在多个config文件,粗暴地取第一个找到的文件显然会导致不确定的结果,更不要说这个文件本身也是可以随意修改的

这个是因为要对于不同的国产硬件做适配的原因,因为dde-daemon全平台共用一套代码,直到v23才分离,所以会存在这种比较粗暴的做法(国产平台有些cpu调度和x86设置不一致)

除去往内核选项里随意加 CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_XXX这样的选项是不是符合规范,单纯用正则匹配到的行来设置变量是不是有点过于不专业了?就像我的改法,只要把未解开设置也未设置值的选项移动到上面的位置,就可以影响代码的执行结果,实在是有点扯了吧?

这个我确实不太了解,会和相应开发人员讨论后答复

为什么已经发布的版本,却在Github上找不到对应的源代码,那这还算是“开源项目”吗?要不是知道可以用 apt source 下载源码,我不知道还要自己瞎琢磨吓找多久;不光是这个版本的 dde-daemon,我之前找屏幕分辨率的问题时就发现了Github上找不到正确版本的startdde(系统版本5.9.70,开源版本则是5.9.64);另外还有上面代码里的 utils.FindContentInFileRegexp方法,看上去来自https://github.com/linuxdeepin/go-lib/tree/master/utils,实际去找却根本找不到这个方法,也就是说下载到的这份代码在我机器上根本就编译不了,要不是这个问题还算简单,看代码猜猜逻辑就够了,否则不知道要花多少时间精力才能解决。

这个问题存在于v20版本,由于我们现在使用的v23系统和v20偏移较大,所以github仓库存储的是v23代码,v20代码不再在github更新,不过你通过源依然可以下载

附图:
图片.png

关于之前的性能设置问题,我是发现:

1.设置为平衡模式时 实际设置的为高性能模式关闭睿频(boots),并不是我们所理解的平衡模式。

2 对于intel pstate并没有做到支持

这俩个问题已经反馈给项目组进行过修改。

感谢楼主对于deepin开源项目的关心

如果涉及技术方面的问题,楼主可以来github发帖,或者来matrix与我们的研发人员直接交流

Reply View the author
蔡EEPIN
deepin
2023-04-28 22:59
#10

终于有大佬说电源管理的问题了,我笔记本根本不敢用deepin 太热了。。

Reply View the author
DebuggerX
deepin
2023-04-28 23:06
#11
longlong

这个我来详细解释下,我是发现这个性能模式问题的人,同时也给dde-daemon组提出这个问题:

怎么会想到用config文件来判断呢?要知道用户可能会安装多个版本的内核,boot目录下就会存在多个config文件,粗暴地取第一个找到的文件显然会导致不确定的结果,更不要说这个文件本身也是可以随意修改的

这个是因为要对于不同的国产硬件做适配的原因,因为dde-daemon全平台共用一套代码,直到v23才分离,所以会存在这种比较粗暴的做法(国产平台有些cpu调度和x86设置不一致)

除去往内核选项里随意加 CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_XXX这样的选项是不是符合规范,单纯用正则匹配到的行来设置变量是不是有点过于不专业了?就像我的改法,只要把未解开设置也未设置值的选项移动到上面的位置,就可以影响代码的执行结果,实在是有点扯了吧?

这个我确实不太了解,会和相应开发人员讨论后答复

为什么已经发布的版本,却在Github上找不到对应的源代码,那这还算是“开源项目”吗?要不是知道可以用 apt source 下载源码,我不知道还要自己瞎琢磨吓找多久;不光是这个版本的 dde-daemon,我之前找屏幕分辨率的问题时就发现了Github上找不到正确版本的startdde(系统版本5.9.70,开源版本则是5.9.64);另外还有上面代码里的 utils.FindContentInFileRegexp方法,看上去来自https://github.com/linuxdeepin/go-lib/tree/master/utils,实际去找却根本找不到这个方法,也就是说下载到的这份代码在我机器上根本就编译不了,要不是这个问题还算简单,看代码猜猜逻辑就够了,否则不知道要花多少时间精力才能解决。

这个问题存在于v20版本,由于我们现在使用的v23系统和v20偏移较大,所以github仓库存储的是v23代码,v20代码不再在github更新,不过你通过源依然可以下载

附图:
图片.png

关于之前的性能设置问题,我是发现:

1.设置为平衡模式时 实际设置的为高性能模式关闭睿频(boots),并不是我们所理解的平衡模式。

2 对于intel pstate并没有做到支持

这俩个问题已经反馈给项目组进行过修改。

感谢楼主对于deepin开源项目的关心

如果涉及技术方面的问题,楼主可以来github发帖,或者来matrix与我们的研发人员直接交流

以前确实也存在问题,只是没那么明显,所以我也没有特别去看过。

关于你的回复,20版本代码没有全部放到Github这个事情,我之前是没有听说过的,不知道官方有没有过明确的说明,既然现在知道了那也就无所谓了。

至于第一个问题,为了兼容国产硬件的说法恕我没法接受,理由我应该已经阐述清楚了,在我看来不管什么硬件,这个思路都是难以保证可用性的。

而关于config文件内的选项问题,我刚才测试了源里最新的两个内核:

  • linux-image-5.18.17-amd64-desktop-hwe:没有CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_XXX,CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y在最上面
  • linux-image-6.1.0:情况和上面的一致,而且config文件名是config-6.1.0,甚至无法被正则匹配到

按我理解,即使确认使用这个方案,也要有相应的内核deb包支持,并在系统更新的时候强制更新吧,现在种情况算什么呢

Reply View the author
fslong
deepin beta test group
2023-04-28 23:07
#12

核心原因在于deepin之前只写了两个电源调度,开发想要给你搓出个平衡模式,就得用其他骚操作了,比如关闭睿频、降频等等。

f550a58abc235cd590d4372aed53dcd.png

正常来讲,应该有很多调度的,玩过安卓手机的小伙伴估计也有印象:

image.png

事实上由于有功耗墙以及发热降频的存在,performance下跑分不一定比ondemand高,表现真不一定好。

实在没办法我都特意在zshrc中写了个个function来解决deepin电源的问题,发热的时候我就手动降频一下:

image.png

测过跑分,这个配置跟performance只差了一丢丢。

但这个问题在20.9上已经修复了,上次更新已经添加了很多调度:

image.png

理论上控制中心应该有好几个可以选的了,然而现在还没写其他的调度。

更让人郁闷的是,目前v23还没有更新这块东西,还得再等等。

Reply View the author
DebuggerX
deepin
2023-04-28 23:15
#13
fslong

核心原因在于deepin之前只写了两个电源调度,开发想要给你搓出个平衡模式,就得用其他骚操作了,比如关闭睿频、降频等等。

f550a58abc235cd590d4372aed53dcd.png

正常来讲,应该有很多调度的,玩过安卓手机的小伙伴估计也有印象:

image.png

事实上由于有功耗墙以及发热降频的存在,performance下跑分不一定比ondemand高,表现真不一定好。

实在没办法我都特意在zshrc中写了个个function来解决deepin电源的问题,发热的时候我就手动降频一下:

image.png

测过跑分,这个配置跟performance只差了一丢丢。

但这个问题在20.9上已经修复了,上次更新已经添加了很多调度:

image.png

理论上控制中心应该有好几个可以选的了,然而现在还没写其他的调度。

更让人郁闷的是,目前v23还没有更新这块东西,还得再等等。

不是deepin只写了两种模式,而是因为你使用的驱动是intel_pstate

而我的机器使用的是intel_cpufreq驱动,所以是支持内核的那些调度器的:

image.png

image.png

Reply View the author
longlong
deepin
Developer
2023-04-28 23:20
#14
DebuggerX

以前确实也存在问题,只是没那么明显,所以我也没有特别去看过。

关于你的回复,20版本代码没有全部放到Github这个事情,我之前是没有听说过的,不知道官方有没有过明确的说明,既然现在知道了那也就无所谓了。

至于第一个问题,为了兼容国产硬件的说法恕我没法接受,理由我应该已经阐述清楚了,在我看来不管什么硬件,这个思路都是难以保证可用性的。

而关于config文件内的选项问题,我刚才测试了源里最新的两个内核:

  • linux-image-5.18.17-amd64-desktop-hwe:没有CONFIG_CPU_FREQ_DEFAULT_GOV_DDE_XXX,CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y在最上面
  • linux-image-6.1.0:情况和上面的一致,而且config文件名是config-6.1.0,甚至无法被正则匹配到

按我理解,即使确认使用这个方案,也要有相应的内核deb包支持,并在系统更新的时候强制更新吧,现在种情况算什么呢

这个问题已经和相应开发人员反馈了,不过我并不是dde-deamon的维护者。就没办法给你进一步详细解释。不过根据我了解到的情况,这个行为确实是为了去支持国产硬件才做的操作,因为你在sys目录下看到的电源模式并不一定能设置成功。所以联合内核那边定义了这个行为,理论上这个机制并不会推到社区版本。

Reply View the author
longlong
deepin
Developer
2023-04-28 23:22
#15
DebuggerX

不是deepin只写了两种模式,而是因为你使用的驱动是intel_pstate

而我的机器使用的是intel_cpufreq驱动,所以是支持内核的那些调度器的:

image.png

image.png

我们之前的行为平衡模式是 高性能+关闭boost,所以并不正确。 后续我们已经做了修改,应该是符合内核文档定义的那几种节电模式 :相关提交:https://github.com/linuxdeepin/dde-daemon/pull/397/files

Reply View the author
fslong
deepin beta test group
2023-04-28 23:25
#16
DebuggerX

不是deepin只写了两种模式,而是因为你使用的驱动是intel_pstate

而我的机器使用的是intel_cpufreq驱动,所以是支持内核的那些调度器的:

image.png

image.png

可是我啥都没动过呀,我那台20.9的机器以前就只有这两种调度,现在有这么多了。

Reply View the author
DebuggerX
deepin
2023-04-28 23:29
#17
longlong

这个问题已经和相应开发人员反馈了,不过我并不是dde-deamon的维护者。就没办法给你进一步详细解释。不过根据我了解到的情况,这个行为确实是为了去支持国产硬件才做的操作,因为你在sys目录下看到的电源模式并不一定能设置成功。所以联合内核那边定义了这个行为,理论上这个机制并不会推到社区版本。

了解了,谢谢。

不过即使不去纠结为什么这样的做法在国产硬件上就能行得通,我个人还是认为,这种为了适配国产硬件而损害其他硬件用户的做法有点本末倒置、倒行逆施了

Reply View the author
fslong
deepin beta test group
2023-04-28 23:36
#18
DebuggerX

不是deepin只写了两种模式,而是因为你使用的驱动是intel_pstate

而我的机器使用的是intel_cpufreq驱动,所以是支持内核的那些调度器的:

image.png

image.png

我看了下,现在20.9用的是intel_cpufreq,之前用的是intel_pstate。

我的23关了intel_pstate也就用的intel_cpufreq了。

Reply View the author
longlong
deepin
Developer
2023-04-28 23:36
#19
DebuggerX

了解了,谢谢。

不过即使不去纠结为什么这样的做法在国产硬件上就能行得通,我个人还是认为,这种为了适配国产硬件而损害其他硬件用户的做法有点本末倒置、倒行逆施了

是的,所以23会和20独立开发,23的适配对象就是普通用户,而不会因为某些特殊硬件去妥协。很感谢你对于此问题的反馈。这将帮助我们更早更快的解决问题,如果你以后在开发和使用的时候遇到问题,欢迎直接来github反馈或者提pr,或者来matirx和研发同学一起“摸鱼”

顺便,指出你文章的一个小bug: 在/boot 目录下的文件并不能被随便修改,需要root权限的

Reply View the author
fslong
deepin beta test group
2023-04-28 23:42
#20

感谢楼主,在楼主的启发下,我的v23改成了intel_cpufreq,真是舒服。

另外,关闭intel_pstate之后,默认会启用ondermand的调度,这个目前测试比较平衡舒服。

但如果你在控制中心动了电源管理,切换到平衡或者高性能,调度又会变成performance,立马开始发烫了,重启才会好。

只关闭intel_pstate:

image.png

切换到平衡模式:

image.png

切换到高性能模式:

image.png

Reply View the author
1 / 2
To page