├── Resources
└── phoenix-96.ico
├── UI
├── ToolStripRenderer.cs
├── AboutForm.en.resx
├── MainForm.en.resx
├── AboutForm.cs
├── AboutForm.Designer.cs
├── MainForm.resx
└── MainForm.cs
├── Makefile
├── Properties
├── Resources.en.resx
├── AssemblyInfo.cs
├── Resources.Designer.cs
├── Settings.settings
├── Strings.en.resx
├── Strings.resx
├── Resources.resx
├── Settings.Designer.cs
└── Strings.Designer.cs
├── Common
├── Hardware
│ ├── UpdateVisitor.cs
│ └── HardwareMonitor.cs
├── Container
│ ├── AppContainer.cs
│ └── Container.cs
├── Awake.cs
├── PowerConfig.cs
├── Processor
│ ├── AMDProcessor.cs
│ └── RyzenAdj.cs
├── Logger
│ └── SimpleLogger.cs
└── EnergyStar
│ ├── Interop
│ └── Win32Api.cs
│ └── EnergyManager.cs
├── packages.config
├── LICENSE.md
├── RyzenTuner.sln
├── Utils
├── CommonUtils.cs
├── DebugUtils.cs
├── RyzenAdjUtils.cs
└── RyzenTunerUtils.cs
├── app.manifest
├── .github
└── workflows
│ └── debug_build.yml
├── README-CN.md
├── .gitattributes
├── README.md
├── App.config
├── Program.cs
├── .gitignore
├── RyzenTuner.csproj
└── docs
└── AMD_Ryzen7_6850HS.md
/Resources/phoenix-96.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zqhong/RyzenTuner/HEAD/Resources/phoenix-96.ico
--------------------------------------------------------------------------------
/UI/ToolStripRenderer.cs:
--------------------------------------------------------------------------------
1 | using System.Drawing;
2 | using System.Windows.Forms;
3 |
4 | namespace RyzenTuner.UI
5 | {
6 | public class ToolStripRenderer : ToolStripProfessionalRenderer
7 | {
8 | protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
9 | {
10 | if (e.Item is ToolStripMenuItem { Checked: true } item)
11 | {
12 | e.TextFont = new Font(item.Font, FontStyle.Bold);
13 | }
14 |
15 | base.OnRenderItemText(e);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | NAME=RyzenTuner
2 | VERSION=$(shell git describe --tags --abbrev=0 || echo "unknown version")
3 | BUILD_TIME=$(shell date "+%Y%m%d%H%M%S")
4 |
5 | RELEASE_FILE_NAME=$(shell echo $(NAME)-$(VERSION)-$(BUILD_TIME).zip)
6 |
7 | release:
8 | rm -rf bin/tmp
9 | cp -r bin/Release bin/tmp
10 | cd bin/tmp && rm -f *.xml *.log *.pdb *.stackdump && rm -rf tmp
11 | cd bin/tmp && sed -i 's#Debug#Warning#g' RyzenTuner.exe.config
12 | cd bin/tmp && zip -r -9 $(RELEASE_FILE_NAME) ./*
13 | mv bin/tmp/$(RELEASE_FILE_NAME) bin/
14 | rm -rf bin/tmp
15 |
--------------------------------------------------------------------------------
/UI/AboutForm.en.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 | text/microsoft-resx
4 |
5 |
6 | 1.3
7 |
8 |
9 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
10 |
11 |
12 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
13 |
14 |
--------------------------------------------------------------------------------
/UI/MainForm.en.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 | text/microsoft-resx
4 |
5 |
6 | 1.3
7 |
8 |
9 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
10 |
11 |
12 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
13 |
14 |
--------------------------------------------------------------------------------
/Properties/Resources.en.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 | text/microsoft-resx
4 |
5 |
6 | 1.3
7 |
8 |
9 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
10 |
11 |
12 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
13 |
14 |
--------------------------------------------------------------------------------
/Common/Hardware/UpdateVisitor.cs:
--------------------------------------------------------------------------------
1 | using LibreHardwareMonitor.Hardware;
2 |
3 | namespace RyzenTuner.Common.Hardware
4 | {
5 | public class UpdateVisitor : IVisitor
6 | {
7 | public void VisitComputer(IComputer computer)
8 | {
9 | // Triggers the "IElement.Accept" method with the given visitor for each device in each group.
10 | computer.Traverse(this);
11 | }
12 |
13 | public void VisitHardware(IHardware hardware)
14 | {
15 | hardware.Update();
16 | foreach (var subHardware in hardware.SubHardware) subHardware.Accept(this);
17 | }
18 |
19 | public void VisitSensor(ISensor sensor)
20 | {
21 | }
22 |
23 | public void VisitParameter(IParameter parameter)
24 | {
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // 文件说明
5 | [assembly: AssemblyTitle("RyzenTuner")]
6 | [assembly: AssemblyDescription("")]
7 | [assembly: AssemblyConfiguration("")]
8 | [assembly: AssemblyCompany("")]
9 | // 产品名称
10 | [assembly: AssemblyProduct("RyzenTuner")]
11 | // 版权
12 | [assembly: AssemblyCopyright("Copyright © 2025")]
13 | // 合法商标
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("ebc428a6-134e-4b8b-8b89-3595ff804785")]
24 |
25 | // Major.Minor.Build.Revision
26 | // 程序集的版本信息由下列四个值组成:
27 | //
28 | // 年份
29 | // 月份
30 | // 版本号
31 | // 修订号
32 | [assembly: AssemblyVersion("2025.6.0.000")]
33 | [assembly: AssemblyFileVersion("2025.6.0.000")]
--------------------------------------------------------------------------------
/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/UI/AboutForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using RyzenTuner.Common.Container;
4 |
5 | namespace RyzenTuner.UI
6 | {
7 | public partial class AboutForm : Form
8 | {
9 | public AboutForm()
10 | {
11 | InitializeComponent();
12 |
13 | richTextBox1.Text = richTextBox1.Text.Replace("{version}",
14 | $"V{System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()}");
15 | richTextBox1.Text = richTextBox1.Text.Replace("{copyright_year}", DateTime.Now.Year.ToString());
16 |
17 | richTextBox1.ReadOnly = true;
18 | richTextBox1.Enabled = false;
19 | }
20 |
21 | private void AboutForm_Load(object sender, EventArgs e)
22 | {
23 | // Form 标题
24 | Text = Properties.Strings.TextAbout;
25 | }
26 |
27 | private void richTextBox1_TextChanged(object sender, EventArgs e)
28 | {
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 zqhong
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/RyzenTuner.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32210.238
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RyzenTuner", "RyzenTuner.csproj", "{EBC428A6-134E-4B8B-8B89-3595FF804785}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Release|Any CPU = Release|Any CPU
11 | Debug|Any CPU = Debug|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {EBC428A6-134E-4B8B-8B89-3595FF804785}.Release|Any CPU.ActiveCfg = Release|Any CPU
15 | {EBC428A6-134E-4B8B-8B89-3595FF804785}.Release|Any CPU.Build.0 = Release|Any CPU
16 | {EBC428A6-134E-4B8B-8B89-3595FF804785}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {EBC428A6-134E-4B8B-8B89-3595FF804785}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {F11E1A3C-B828-4300-A194-F827D77B8C63}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/Utils/CommonUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Drawing;
4 | using System.IO;
5 | using System.Runtime.InteropServices;
6 |
7 | namespace RyzenTuner.Utils
8 | {
9 | public static class CommonUtils
10 | {
11 | /**
12 | * 检查系统是否处于锁屏状态
13 | */
14 | public static bool IsSystemLocked()
15 | {
16 | // logonui,即 Windows Logon User Interface Host,翻译为【登录用户界面】
17 | return Process.GetProcessesByName("logonui").Length > 0;
18 | }
19 |
20 | /**
21 | * 检查字体是否存在
22 | */
23 | public static bool IsFontExists(string fontName)
24 | {
25 | const float fontSize = 12;
26 |
27 | using var fontTester = new Font(
28 | fontName,
29 | fontSize,
30 | FontStyle.Regular,
31 | GraphicsUnit.Pixel);
32 |
33 | return fontTester.Name == fontName;
34 | }
35 |
36 | /**
37 | * 检查提供的日期是否处于晚上
38 | */
39 | public static bool IsNight(DateTime now)
40 | {
41 | TimeSpan nightShiftStart = new TimeSpan(23, 59, 0); // 23:59pm
42 | TimeSpan nightShiftEnd = new TimeSpan(7, 0, 0); // 7:00am
43 |
44 | if (now.TimeOfDay > nightShiftStart || now.TimeOfDay < nightShiftEnd)
45 | {
46 | return true;
47 | }
48 |
49 | return false;
50 | }
51 | }
52 | }
--------------------------------------------------------------------------------
/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/Utils/DebugUtils.cs:
--------------------------------------------------------------------------------
1 | using RyzenTuner.Common.Container;
2 |
3 | namespace RyzenTuner.Utils
4 | {
5 | public static class DebugUtils
6 | {
7 | ///
8 | /// 记录 Cpu 在不同限制功耗下的数据
9 | ///
10 | /// 备注:仅在开发使用
11 | ///
12 | public static void LogCpuInfo()
13 | {
14 | AppContainer.HardwareMonitor().Monitor();
15 | AppContainer.AmdProcessor().SetTctlTemp(90);
16 |
17 | AppContainer.PowerConfig().DisableCpuBoost();
18 | AppContainer.Logger().Debug("关闭睿频");
19 | _logCpuInfo();
20 |
21 | AppContainer.PowerConfig().EnableCpuBoost();
22 | AppContainer.Logger().Debug("开启睿频");
23 | _logCpuInfo();
24 | }
25 |
26 | private static void _logCpuInfo()
27 | {
28 | const int maxPowerLimit = 30;
29 | var hardware = AppContainer.HardwareMonitor();
30 |
31 | for (var i = 1; i <= maxPowerLimit; i++)
32 | {
33 | AppContainer.AmdProcessor().SetFastPPT(i);
34 | AppContainer.AmdProcessor().SetSlowPPT(i);
35 | AppContainer.AmdProcessor().SetStampPPT(i);
36 |
37 | System.Threading.Thread.Sleep(2048);
38 | AppContainer.HardwareMonitor().Monitor();
39 |
40 | AppContainer.Logger()
41 | .Debug(
42 | $"功率:限制{i}瓦、实际{hardware.CpuPackagePower:F}瓦,CPU:{hardware.CpuUsage:F}%、{hardware.CpuTemperature:F}℃、{hardware.CpuFreq:F}MHz,GPU:{hardware.VideoCard3DUsage:F}%");
43 | }
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Common/Container/AppContainer.cs:
--------------------------------------------------------------------------------
1 | using RyzenTuner.Common.EnergyStar;
2 | using RyzenTuner.Common.Logger;
3 | using RyzenTuner.Common.Processor;
4 |
5 | namespace RyzenTuner.Common.Container
6 | {
7 | /**
8 | * Refer: https://csharpindepth.com/articles/singleton#cctor
9 | */
10 | public static class AppContainer
11 | {
12 | private static readonly Container Container;
13 |
14 | static AppContainer()
15 | {
16 | Container = new Container();
17 |
18 | Container.Register(() => new Hardware.HardwareMonitor())
19 | .AsSingleton();
20 |
21 | Container.Register(() => new PowerConfig())
22 | .AsSingleton();
23 |
24 | Container.Register(() => new AmdProcessor())
25 | .AsSingleton();
26 |
27 | Container.Register(() => new EnergyManager())
28 | .AsSingleton();
29 |
30 | Container.Register(() =>
31 | {
32 | var logger = new SimpleLogger();
33 | logger.DefaultLogLevel = logger.ToLogLevel(Properties.Settings.Default.LogLevel);
34 | return logger;
35 | })
36 | .AsSingleton();
37 | }
38 |
39 | public static Hardware.HardwareMonitor HardwareMonitor()
40 | {
41 | return Container.Resolve();
42 | }
43 |
44 | public static PowerConfig PowerConfig()
45 | {
46 | return Container.Resolve();
47 | }
48 |
49 | public static AmdProcessor AmdProcessor()
50 | {
51 | return Container.Resolve();
52 | }
53 |
54 | public static EnergyManager EnergyManager()
55 | {
56 | return Container.Resolve();
57 | }
58 |
59 | public static SimpleLogger Logger()
60 | {
61 | return Container.Resolve();
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/.github/workflows/debug_build.yml:
--------------------------------------------------------------------------------
1 | name: RyzenTuner Debug Build
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | logLevel:
7 | description: 'Log level'
8 | required: true
9 | default: 'warning'
10 | type: choice
11 | options:
12 | - info
13 | - warning
14 | - debug
15 |
16 | jobs:
17 | build:
18 | strategy:
19 | matrix:
20 | configuration: [ Debug ]
21 | platform: [ x64 ]
22 |
23 | runs-on: windows-latest
24 |
25 | env:
26 | Solution_Name: RyzenTuner.sln
27 | Project_Name: RyzenTuner
28 |
29 | steps:
30 | - name: Checkout
31 | uses: actions/checkout@v3
32 | with:
33 | fetch-depth: 0
34 |
35 | - name: Setup MSBuild.exe
36 | uses: microsoft/setup-msbuild@v1.1
37 |
38 | - name: Setup NuGet
39 | uses: nuget/setup-nuget@v1
40 |
41 | - name: Restore Packages
42 | run: nuget restore $env:Solution_Name
43 |
44 | - name: Build
45 | run: msbuild $env:Solution_Name
46 |
47 | - name: Install packages
48 | run: |
49 | choco install wget --no-progress
50 | choco install unzip --no-progress
51 |
52 | - name: Add dependencies
53 | run: |
54 | wget -O libryzenadj-win64.zip https://github.com/FlyGoat/RyzenAdj/releases/download/v0.12.0/libryzenadj-win64.zip
55 | unzip libryzenadj-win64.zip
56 | cp build/libryzenadj.dll ./bin/Debug
57 | cp win32/inpoutx64.dll ./bin/Debug
58 | cp win32/WinRing0x64.dll ./bin/Debug
59 | cp win32/WinRing0x64.sys ./bin/Debug
60 |
61 | - name: Generate artifact name
62 | id: generate-name
63 | run: |
64 | echo "::set-output name=artifact::${{ github.event.repository.name }}.${{ github.ref_name }}.${{ github.run_id }}.zip"
65 |
66 | - name: Upload artifact
67 | uses: actions/upload-artifact@v2
68 | with:
69 | name: ${{ steps.generate-name.outputs.artifact }}
70 | path: "./bin/Debug"
--------------------------------------------------------------------------------
/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | namespace RyzenTuner.Properties {
11 | using System;
12 |
13 |
14 | [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
15 | [System.Diagnostics.DebuggerNonUserCodeAttribute()]
16 | [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
17 | internal class Resources {
18 |
19 | private static System.Resources.ResourceManager resourceMan;
20 |
21 | private static System.Globalization.CultureInfo resourceCulture;
22 |
23 | [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
24 | internal Resources() {
25 | }
26 |
27 | [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
28 | internal static System.Resources.ResourceManager ResourceManager {
29 | get {
30 | if (object.Equals(null, resourceMan)) {
31 | System.Resources.ResourceManager temp = new System.Resources.ResourceManager("RyzenTuner.Properties.Resources", typeof(Resources).Assembly);
32 | resourceMan = temp;
33 | }
34 | return resourceMan;
35 | }
36 | }
37 |
38 | [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static System.Globalization.CultureInfo Culture {
40 | get {
41 | return resourceCulture;
42 | }
43 | set {
44 | resourceCulture = value;
45 | }
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/UI/AboutForm.Designer.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace RyzenTuner.UI
4 | {
5 | partial class AboutForm
6 | {
7 | ///
8 | /// Required designer variable.
9 | ///
10 | private IContainer components = null;
11 |
12 | ///
13 | /// Clean up any resources being used.
14 | ///
15 | /// true if managed resources should be disposed; otherwise, false.
16 | protected override void Dispose(bool disposing)
17 | {
18 | if (disposing && (components != null))
19 | {
20 | components.Dispose();
21 | }
22 |
23 | base.Dispose(disposing);
24 | }
25 |
26 | #region Windows Form Designer generated code
27 |
28 | ///
29 | /// Required method for Designer support - do not modify
30 | /// the contents of this method with the code editor.
31 | ///
32 | private void InitializeComponent()
33 | {
34 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(AboutForm));
35 | this.richTextBox1 = new System.Windows.Forms.RichTextBox();
36 | this.SuspendLayout();
37 | //
38 | // richTextBox1
39 | //
40 | resources.ApplyResources(this.richTextBox1, "richTextBox1");
41 | this.richTextBox1.Name = "richTextBox1";
42 | this.richTextBox1.TextChanged += new System.EventHandler(this.richTextBox1_TextChanged);
43 | //
44 | // AboutForm
45 | //
46 | resources.ApplyResources(this, "$this");
47 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
48 | this.Controls.Add(this.richTextBox1);
49 | this.Name = "AboutForm";
50 | this.Load += new System.EventHandler(this.AboutForm_Load);
51 | this.ResumeLayout(false);
52 | }
53 |
54 | private System.Windows.Forms.RichTextBox richTextBox1;
55 |
56 | #endregion
57 | }
58 | }
--------------------------------------------------------------------------------
/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | False
7 |
8 |
9 | False
10 |
11 |
12 | 16
13 |
14 |
15 | 16
16 |
17 |
18 | 8
19 |
20 |
21 | 16
22 |
23 |
24 | 26
25 |
26 |
27 | 45
28 |
29 |
30 | AutoMode
31 |
32 |
33 | Debug
34 |
35 |
36 | example1.exe,example2.exe
37 |
38 |
39 | 100
40 |
41 |
42 | 51
43 |
44 |
45 | 45
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/README-CN.md:
--------------------------------------------------------------------------------
1 | ## RyzenTuner
2 |
3 | [English](README.md) | 简体中文
4 |
5 | RyzenTuner 提供一个 GUI 界面,可以方便调节 Ryzen 移动处理器的功率限制,也支持调整 Windows 进程的 QoS 等级和优先级,从而提升电池使用时间和减少风扇噪声。
6 |
7 | 
8 |
9 | ## 添加内容
10 |
11 | ### 自动模式
12 |
13 | 根据插电/电池/夜晚/活跃时间等不同条件,自动选择不同的工作模式(待机/平衡/性能)。
14 |
15 | 工作模式说明:
16 |
17 | * 待机模式(SleepMode):处于最低能耗状态,只能应对超低负载的工作
18 | * 平衡模式(BalancedMode):能耗比最高的状态,应对突发的任务,比如打开网页、Photoshop
19 | * 性能模式(PerformanceMode):应对需要高性能的场景,比如编译软件、玩大型游戏、渲染等
20 |
21 | ## 使用
22 |
23 | 你可以直接到 [Release](https://github.com/zqhong/RyzenTuner/releases) 下载编译好的程序使用。
24 |
25 | ## FAQ
26 |
27 | ### 如何修改待机模式等其他模式的功率
28 |
29 | 关闭 `RyzenTuner`。打开 `RyzenTuner.exe.config` 文件,修改对应的参数。比如 `SleepMode` 就是 睡眠模式,修改其中的 value 值。
30 |
31 | 示例:将睡眠模式从 1 W 改为 2 W
32 |
33 | 修改前
34 |
35 | ```xml
36 |
37 |
38 | 1
39 |
40 | ```
41 |
42 | 修改后
43 |
44 | ```xml
45 |
46 |
47 | 2
48 |
49 | ```
50 |
51 | ## 计划
52 |
53 | - [x] 多语言支持
54 | - [x] GitHub action
55 | - [ ] 开机启动
56 | - [ ] 添加设置面板
57 | - [ ] 添加是否允许修改电源计划的选项,默认关闭
58 | - [ ] 添加应用策略,支持不同应用自定义切换不同的功率限制模式
59 |
60 | ## 附录
61 |
62 | ### 问题记录
63 |
64 | AMD 6850HS 处理器、Windows 11 22H2 系统
65 |
66 | ryzenadj 0.17.0、0.16.0、0.15.0、0.14.0、0.13.0、0.12.0、0.11.1 存在问题:
67 |
68 | * 异常情况
69 | * stamp-limit 设置不生效;
70 | * fast-limit 影响 stamp-limit 和 fast-limit 的值;
71 | * fast-limit 最大值:51瓦;slow-limit 最大值 41瓦;比如设置 fast-limit 为 55 瓦,结果为 51 瓦
72 | * 正常情况
73 | * slow-limit 设置正常生效;
74 | * tctl-temp 设置正常生效
75 |
76 | ## Give a Star! ⭐
77 |
78 | 如果你喜欢或正在使用这个项目,请给我们一个 star。一个小小的 star 是作者更新项目/回答问题的动力!🤝
79 |
80 | [](#RyzenTuner)
81 |
82 | ## 依赖的项目
83 |
84 | * [Archeb/RyzenTuner](https://github.com/Archeb/RyzenTuner):基于该项目开发
85 | * [FlyGoat/RyzenAdj](https://github.com/FlyGoat/RyzenAdj):Ryzen 移动处理器电源管理工具
86 | * [imbushuo/EnergyStar](https://github.com/imbushuo/EnergyStar):Windows 进程调度,可能有增加续航的效果(未测试)
87 | * [LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor):获取硬件信息
88 | * [dahall/Vanara](https://github.com/dahall/Vanara):一套 .NET 库,包含了许多 Windows 原生 API 的 PInvoke 调用的封装
89 |
90 | 感谢以上名单的项目和作者。
91 |
92 | ## License
93 |
94 | RyzenTuner 使用 [MIT](LICENSE.md) 开源协议。
--------------------------------------------------------------------------------
/Properties/Strings.en.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 | text/microsoft-resx
4 |
5 |
6 | 1.3
7 |
8 |
9 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
10 |
11 |
12 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
13 |
14 |
15 | Automatic
16 |
17 |
18 | Balance
19 |
20 |
21 | Manual
22 |
23 |
24 | Performance
25 |
26 |
27 | Power Saving
28 |
29 |
30 | Standby
31 |
32 |
33 | Power Limit
34 |
35 |
36 | Other Options
37 |
38 |
39 | Stay Awake
40 |
41 |
42 | Enable EnergyStar
43 |
44 |
45 | About
46 |
47 |
48 | RyzenTuner has an error
49 |
50 |
51 | Only one RyzenTuner program is allowed to run at a time
52 |
53 |
54 | Power: limited {power_limit}W, actual {actual_power_limit}W
55 |
56 |
57 | Exit
58 |
59 |
--------------------------------------------------------------------------------
/Properties/Strings.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | text/microsoft-resx
11 |
12 |
13 | 1.3
14 |
15 |
16 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
17 |
18 |
19 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
20 |
21 |
22 | 自动模式
23 |
24 |
25 | 平衡模式
26 |
27 |
28 | 手动模式
29 |
30 |
31 | 性能模式
32 |
33 |
34 | 省电模式
35 |
36 |
37 | 待机模式
38 |
39 |
40 | 功率限制
41 |
42 |
43 | 其他选项
44 |
45 |
46 | 保持唤醒
47 |
48 |
49 | 开启 EnergyStar
50 |
51 |
52 | 关于
53 |
54 |
55 | RyzenTuner 出现错误
56 |
57 |
58 | 同一时间内,只允许运行一个 RyzenTuner 程序
59 |
60 |
61 | 功率:限制{power_limit}W、实际{actual_power_limit}W
62 |
63 |
64 | 退出
65 |
66 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## RyzenTuner
2 |
3 | English | [简体中文](README-CN.md)
4 |
5 | RyzenTuner provides a GUI interface to easily adjust the power limit of Ryzen mobile processors, and also supports adjusting the QoS level and priority of Windows processes, thereby improving battery life and reducing fan noise.
6 |
7 | 
8 |
9 | ## Feature
10 |
11 | ### Automatic Mode
12 |
13 | Different working modes (standby/balance/performance) are automatically selected according to different conditions such as plug-in/battery/night/active time.
14 |
15 | Description of working mode:
16 |
17 | * Standby mode: in the lowest energy consumption state, can only deal with ultra-low load work
18 | * Balanced Mode: The state with the highest energy consumption ratio, to deal with sudden tasks, such as opening web
19 | pages, Photoshop
20 | * Performance Mode: for scenarios that require high performance, such as compiling software, playing large games,
21 | rendering, etc.
22 |
23 | ## Usage
24 |
25 | You can directly go to [Release](https://github.com/zqhong/RyzenTuner/releases) to download the compiled program and use
26 | it.
27 |
28 | ## FAQ
29 |
30 | ### How to modify the power of other modes such as standby mode
31 |
32 | Close `RyzenTuner`. Open the `RyzenTuner.exe.config` file and modify the corresponding parameters. For example, `SleepMode` is the sleep mode, modify the value in it.
33 |
34 | Example: Change sleep mode from 1 W to 2 W
35 |
36 | Before update
37 |
38 | ```xml
39 |
40 |
41 | 1
42 |
43 | ```
44 |
45 | After update
46 |
47 | ```xml
48 |
49 |
50 | 2
51 |
52 | ```
53 |
54 | ## Give a Star! ⭐
55 |
56 | If you like or are using this project, please give it a star. Thanks!
57 |
58 | [](#RyzenTuner)
59 |
60 |
61 | ## Dependent project
62 |
63 | * [Archeb/RyzenTuner](https://github.com/Archeb/RyzenTuner): Developed based on this project
64 | * [FlyGoat/RyzenAdj](https://github.com/FlyGoat/RyzenAdj): Ryzen mobile processor power management tool
65 | * [imbushuo/EnergyStar](https://github.com/imbushuo/EnergyStar): Windows process scheduling, may have the effect of increasing battery life (not tested)
66 | * [LibreHardwareMonitor](https://github.com/LibreHardwareMonitor/LibreHardwareMonitor): Get hardware information
67 | * [dahall/Vanara](https://github.com/dahall/Vanara): A set of .NET libraries that wraps many PInvoke calls to Windows native APIs
68 |
69 | Thanks to the projects and authors listed above.
70 |
71 | ## License
72 |
73 | RyzenTuner is licensed under [MIT](LICENSE.md).
--------------------------------------------------------------------------------
/Common/Awake.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace RyzenTuner.Common
5 | {
6 | /**
7 | * 参考:
8 | * github.com\PowerToys\src\modules\awake\Awake\Core\NativeMethods.cs
9 | * https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate
10 | * https://www.cnblogs.com/guorongtao/p/13918094.html
11 | */
12 | public static class Awake
13 | {
14 | [Flags]
15 | private enum ExecutionState : uint
16 | {
17 | // 启用离开模式。这个值必须和ES_CONTINUOUS一起指定
18 | ES_AWAYMODE_REQUIRED = 0x00000040,
19 |
20 | // 通知系统,被设置的状态应该保持有效,直到下一次使用ES_CONTINUOUS的调用和其他状态标志之一被清除
21 | ES_CONTINUOUS = 0x80000000,
22 |
23 | // 通过重置显示器的空闲计时器,迫使显示器打开
24 | ES_DISPLAY_REQUIRED = 0x00000002,
25 |
26 | // 通过重置系统空闲定时器,迫使系统处于工作状态
27 | ES_SYSTEM_REQUIRED = 0x00000001,
28 | }
29 |
30 | [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
31 | private static extern ExecutionState SetThreadExecutionState(ExecutionState esFlags);
32 |
33 | /**
34 | * 保持操作系统清醒
35 | */
36 | public static bool KeepingSysAwake(bool keepDisplayOn)
37 | {
38 | bool success;
39 | if (keepDisplayOn)
40 | {
41 | success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS |
42 | ExecutionState.ES_DISPLAY_REQUIRED);
43 | }
44 | else
45 | {
46 | success = SetAwakeState(ExecutionState.ES_SYSTEM_REQUIRED | ExecutionState.ES_CONTINUOUS);
47 | }
48 |
49 | return success;
50 | }
51 |
52 | /**
53 | * 允许系统进入睡眠
54 | */
55 | public static bool AllowSysSleep()
56 | {
57 | return SetAwakeState(ExecutionState.ES_CONTINUOUS);
58 | }
59 |
60 | ///
61 | /// 使一个应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入睡眠状态或关闭显示器。
62 | ///
63 | /// 在没有ES_CONTINUOUS的情况下调用SetThreadExecutionState,只是简单地重置了空闲计时器;为了保持显示或系统处于工作状态,线程必须定期地调用SetThreadExecutionState。
64 | /// 备注:这个函数不会阻止屏幕保护程序的执行
65 | ///
66 | /// Single or multiple EXECUTION_STATE entries.
67 | /// true if successful, false if failed
68 | private static bool SetAwakeState(ExecutionState state)
69 | {
70 | try
71 | {
72 | var stateResult = SetThreadExecutionState(state);
73 | return stateResult != 0;
74 | }
75 | catch
76 | {
77 | return false;
78 | }
79 | }
80 | }
81 | }
--------------------------------------------------------------------------------
/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 | False
18 |
19 |
20 | False
21 |
22 |
23 | 16
24 |
25 |
26 | 16
27 |
28 |
29 | 8
30 |
31 |
32 | 16
33 |
34 |
35 | 26
36 |
37 |
38 | 45
39 |
40 |
41 | AutoMode
42 |
43 |
44 | Debug
45 |
46 |
47 | example1.exe,example2.exe
48 |
49 |
50 | 100
51 |
52 |
53 | 51
54 |
55 |
56 | 45
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/Utils/RyzenAdjUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using RyzenTuner.Common.Container;
4 | using RyzenTuner.Properties;
5 |
6 | namespace RyzenTuner.Utils
7 | {
8 | public class RyzenAdjUtils
9 | {
10 | /**
11 | * 计算自动模式下的限制功率(单位:瓦)
12 | *
13 | * 改进:
14 | * 1、适配不同型号 CPU
15 | */
16 | private static float AutoModePowerLimit()
17 | {
18 | var hardwareMonitor = AppContainer.HardwareMonitor();
19 |
20 | var cpuUsage = hardwareMonitor.CpuUsage;
21 | var videoCard3DUsage = hardwareMonitor.VideoCard3DUsage;
22 | var cpuTemperature = hardwareMonitor.CpuTemperature;
23 |
24 | var isNight = CommonUtils.IsNight(DateTime.Now);
25 |
26 | // 自动模式下,在几个模式下切换:待机、平衡、性能
27 | // 插电模式下
28 | var sleepPower = RyzenTunerUtils.GetPowerLimitByMode("SleepMode");
29 | var balancedPower = RyzenTunerUtils.GetPowerLimitByMode("BalancedMode");
30 | var performancePower = RyzenTunerUtils.GetPowerLimitByMode("PerformanceMode");
31 |
32 |
33 | // 电池模式下,最高性能为【平衡】
34 | if (SystemInformation.PowerStatus.PowerLineStatus == PowerLineStatus.Offline)
35 | {
36 | performancePower = RyzenTunerUtils.GetPowerLimitByMode("BalancedMode");
37 | }
38 |
39 | // 夜晚,最高性能为【平衡】
40 | if (isNight)
41 | {
42 | performancePower = RyzenTunerUtils.GetPowerLimitByMode("BalancedMode");
43 | }
44 |
45 | // 默认使用【平衡】
46 | var powerLimit = balancedPower;
47 |
48 | // 符合下面条件之一的情况下,使用【待机】
49 | var idleSecond = RyzenTunerUtils.GetIdleSecond();
50 | if (
51 | // 条件1:在短时间不活跃使用且笔记本负载较低的情况下,进入待机模式
52 | (idleSecond > 2 && cpuUsage < 5 && videoCard3DUsage < 5) ||
53 |
54 | // 条件2:白天 && 非活跃时间超过 x 分钟 && 笔记本低负载
55 | (!isNight && idleSecond > 4 * 60 && cpuUsage < 10 && videoCard3DUsage < 10) ||
56 |
57 | // 条件3:夜晚 && 非活跃时间超过 x 分钟 && 笔记本中负载
58 | (isNight && idleSecond > 4 * 60 && cpuUsage < 20 && videoCard3DUsage < 20) ||
59 |
60 | // 条件4:锁屏状态下 && 非活跃时间超过 x 秒 && 笔记本中负载
61 | (CommonUtils.IsSystemLocked() && idleSecond > 2 && cpuUsage < 20 && videoCard3DUsage < 20) ||
62 |
63 | // 条件5:锁屏状态下 && 非活跃时间超过 x 秒 && 温度大于 x 度
64 | (CommonUtils.IsSystemLocked() && idleSecond > 2 && cpuTemperature > 52)
65 | )
66 | {
67 | powerLimit = sleepPower;
68 | }
69 |
70 | // 非待机模式 && CPU 占用大于 50%,温度在 65 度以内,使用【性能模式】
71 | if (!RyzenTunerUtils.IsSleepMode(powerLimit) && cpuUsage >= 50 && cpuTemperature < 65)
72 | {
73 | powerLimit = performancePower;
74 | }
75 |
76 | return powerLimit;
77 | }
78 |
79 | public static float GetPowerLimit()
80 | {
81 | var powerLimit = RyzenTunerUtils.GetPowerLimitByMode(Properties.Settings.Default.CurrentMode);
82 |
83 | // 自动模式下,根据系统状态自动调整
84 | if (Settings.Default.CurrentMode == "AutoMode")
85 | {
86 | powerLimit = AutoModePowerLimit();
87 | }
88 |
89 | // 数值修正
90 | if (powerLimit < 0)
91 | {
92 | powerLimit = 1;
93 | }
94 |
95 | return powerLimit;
96 | }
97 |
98 | public static int GetTctlTemp()
99 | {
100 | return Settings.Default.TctlTemp;
101 | }
102 | }
103 | }
--------------------------------------------------------------------------------
/Common/PowerConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Vanara.PInvoke;
3 | using static Vanara.PInvoke.PowrProf;
4 |
5 | namespace RyzenTuner.Common
6 | {
7 | public class PowerConfig
8 | {
9 | private const uint Disabled = 0;
10 | private const uint Enabled = 1;
11 |
12 | /**
13 | * 获取当前激活的电源方案的 GUID
14 | */
15 | private Guid GetActiveScheme()
16 | {
17 | HKEY powerKey = default;
18 | var result = PowerGetActiveScheme(powerKey, out var activeGuidHandle);
19 | if (result != Win32Error.NO_ERROR)
20 | {
21 | throw new Exception(result.ToString());
22 | }
23 |
24 | return activeGuidHandle.ToStructure();
25 | }
26 |
27 | /**
28 | * 检查是否开启了 Cpu Boost
29 | */
30 | private bool IsEnableCpuBoost()
31 | {
32 | HKEY powerKey = default;
33 | var activeGuid = GetActiveScheme();
34 |
35 | PowerReadACValueIndex(
36 | powerKey,
37 | activeGuid,
38 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
39 | GUID_PROCESSOR_PERF_BOOST_MODE,
40 | out var acValue
41 | );
42 |
43 | PowerReadDCValueIndex(
44 | powerKey,
45 | activeGuid,
46 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
47 | GUID_PROCESSOR_PERF_BOOST_MODE,
48 | out var dcValue
49 | );
50 |
51 | return acValue == Enabled && dcValue == Enabled;
52 | }
53 |
54 | /**
55 | * 启用 Cpu Boost
56 | */
57 | public bool EnableCpuBoost()
58 | {
59 | if (IsEnableCpuBoost())
60 | {
61 | return true;
62 | }
63 |
64 | HKEY powerKey = default;
65 | var activeGuid = GetActiveScheme();
66 |
67 | var r1 = PowerWriteACValueIndex(
68 | powerKey,
69 | activeGuid,
70 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
71 | GUID_PROCESSOR_PERF_BOOST_MODE,
72 | Enabled
73 | );
74 |
75 | var r2 = PowerWriteDCValueIndex(
76 | powerKey,
77 | activeGuid,
78 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
79 | GUID_PROCESSOR_PERF_BOOST_MODE,
80 | Enabled
81 | );
82 |
83 | var r3 = PowerSetActiveScheme(powerKey, activeGuid);
84 |
85 | return r1 == Win32Error.NO_ERROR && r2 == Win32Error.NO_ERROR && r3 == Win32Error.NO_ERROR;
86 | }
87 |
88 | /**
89 | * 关闭 Cpu Boost
90 | */
91 | public bool DisableCpuBoost()
92 | {
93 | if (!IsEnableCpuBoost())
94 | {
95 | return true;
96 | }
97 |
98 | HKEY powerKey = default;
99 | var activeGuid = GetActiveScheme();
100 |
101 | var r1 = PowerWriteACValueIndex(
102 | powerKey,
103 | activeGuid,
104 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
105 | GUID_PROCESSOR_PERF_BOOST_MODE,
106 | Disabled
107 | );
108 |
109 | var r2 = PowerWriteDCValueIndex(
110 | powerKey,
111 | activeGuid,
112 | GUID_PROCESSOR_SETTINGS_SUBGROUP,
113 | GUID_PROCESSOR_PERF_BOOST_MODE,
114 | Disabled
115 | );
116 |
117 | var r3 = PowerSetActiveScheme(powerKey, activeGuid);
118 |
119 | return r1 == Win32Error.NO_ERROR && r2 == Win32Error.NO_ERROR && r3 == Win32Error.NO_ERROR;
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using System.Globalization;
4 | using System.Threading;
5 | using System.Windows.Forms;
6 | using RyzenTuner.Common.Container;
7 | using RyzenTuner.UI;
8 |
9 | namespace RyzenTuner
10 | {
11 | internal static class Program
12 | {
13 | [STAThread]
14 | private static void Main()
15 | {
16 | try
17 | {
18 | Application.ThreadException += Application_ThreadException;
19 | AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
20 |
21 | if (Environment.OSVersion.Version.Major >= 6)
22 | {
23 | SetProcessDPIAware();
24 | }
25 |
26 | AutoSelectLang();
27 |
28 | if (Process.GetProcessesByName("RyzenTuner").Length > 1)
29 | {
30 | throw new Exception(Properties.Strings.TextExceptionOnlyOneProgramIsAllowedToRun);
31 | }
32 |
33 | Application.EnableVisualStyles();
34 | Application.SetCompatibleTextRenderingDefault(false);
35 | Application.Run(new MainForm());
36 | }
37 | catch (Exception ex)
38 | {
39 | // 检查是否是初始化失败导致的异常
40 | if (ex.InnerException?.GetType() == typeof(DllNotFoundException) ||
41 | ex.Message.Contains("libryzenadj.dll"))
42 | {
43 | ShowErrorAndExit("Critical Error",
44 | "libryzenadj.dll not found! This component is required.\n\n" +
45 | "Please download it from the official repository: " +
46 | "https://github.com/FlyGoat/RyzenAdj");
47 | }
48 | else
49 | {
50 | ShowErrorAndExit("Fatal Error", $"Unhandled exception: {ex.Message}");
51 | }
52 | }
53 | }
54 |
55 | // 显示错误并退出的辅助方法
56 | static void ShowErrorAndExit(string title, string message)
57 | {
58 | MessageBox.Show(message, title,
59 | MessageBoxButtons.OK, MessageBoxIcon.Error);
60 | Environment.Exit(1);
61 | }
62 |
63 | ///
64 | /// 根据用户系统语言,自动选择合适的语言
65 | ///
66 | private static void AutoSelectLang()
67 | {
68 | var currentCulture = Thread.CurrentThread.CurrentCulture;
69 |
70 | // 非中文环境全部切换为英文
71 | if (!currentCulture.ToString().StartsWith("zh-"))
72 | {
73 | var culture = new CultureInfo("en-US");
74 | CultureInfo.DefaultThreadCurrentCulture = culture;
75 | CultureInfo.DefaultThreadCurrentUICulture = culture;
76 | }
77 | }
78 |
79 | private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
80 | {
81 | _handleUnhandledException(e.Exception);
82 | }
83 |
84 | private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs arg)
85 | {
86 | var e = (Exception)arg.ExceptionObject;
87 | _handleUnhandledException(e);
88 | }
89 |
90 | private static void _handleUnhandledException(Exception ex)
91 | {
92 | MessageBox.Show(ex.Message, Properties.Strings.TextExceptionTitle,
93 | MessageBoxButtons.OK, MessageBoxIcon.Error);
94 |
95 | AppContainer.Logger().LogException(ex);
96 |
97 | Application.Exit();
98 | }
99 |
100 | [System.Runtime.InteropServices.DllImport("user32.dll")]
101 | private static extern bool SetProcessDPIAware();
102 | }
103 | }
--------------------------------------------------------------------------------
/Utils/RyzenTunerUtils.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using RyzenTuner.Common.Container;
4 |
5 | namespace RyzenTuner.Utils
6 | {
7 | public static class RyzenTunerUtils
8 | {
9 | [DllImport("user32.dll")]
10 | static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
11 |
12 | // https://www.pinvoke.net/default.aspx/user32.GetLastInputInfo
13 | // https://docs.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-lastinputinfo
14 | [StructLayout(LayoutKind.Sequential)]
15 | struct LASTINPUTINFO
16 | {
17 | public static readonly int SizeOf = Marshal.SizeOf(typeof(LASTINPUTINFO));
18 |
19 | [MarshalAs(UnmanagedType.U4)] public int cbSize;
20 | [MarshalAs(UnmanagedType.U4)] public UInt32 dwTime;
21 | }
22 |
23 | /**
24 | * 返回系统空闲时间,单位:秒
25 | *
26 | * 参考:
27 | * https://stackoverflow.com/questions/203384/how-to-tell-when-windows-is-inactive
28 | */
29 | public static int GetIdleSecond()
30 | {
31 | var idleTime = 0;
32 | var lastInputInfo = new LASTINPUTINFO();
33 | lastInputInfo.cbSize = Marshal.SizeOf(lastInputInfo);
34 | lastInputInfo.dwTime = 0;
35 |
36 | var envTicks = Environment.TickCount;
37 |
38 | if (GetLastInputInfo(ref lastInputInfo))
39 | {
40 | var lastInputTick = (int)lastInputInfo.dwTime;
41 |
42 | idleTime = envTicks - lastInputTick;
43 | }
44 |
45 | return ((idleTime > 0) ? (idleTime / 1000) : idleTime);
46 | }
47 |
48 |
49 | /**
50 | * 检查当前是否处于【待机模式】
51 | */
52 | public static bool IsSleepMode(float powerLimit)
53 | {
54 | return Math.Abs(powerLimit - GetPowerLimitByMode("SleepMode")) < 0.01;
55 | }
56 |
57 | /**
58 | * 检查当前是否处于【省电模式】
59 | */
60 | public static bool IsPowerSaveModeMode(float powerLimit)
61 | {
62 | return Math.Abs(powerLimit - GetPowerLimitByMode("PowerSaveMode")) < 0.01;
63 | }
64 |
65 | /**
66 | * 检查当前是否处于【平衡模式】
67 | */
68 | public static bool IsBalancedMode(float powerLimit)
69 | {
70 | return Math.Abs(powerLimit - GetPowerLimitByMode("BalancedMode")) < 0.01;
71 | }
72 |
73 | /**
74 | * 检查当前是否处于【性能模式】
75 | */
76 | public static bool IsPerformanceMode(float powerLimit)
77 | {
78 | return Math.Abs(powerLimit - GetPowerLimitByMode("PerformanceMode")) < 0.01;
79 | }
80 |
81 | public static float GetPowerLimitByMode(string mode)
82 | {
83 | return float.Parse(Properties.Settings.Default[mode].ToString());
84 | }
85 |
86 | public static string GetNoticeText()
87 | {
88 | var hardwareMonitor = AppContainer.HardwareMonitor();
89 | var powerLimit = RyzenAdjUtils.GetPowerLimit();
90 |
91 | var powerLimitText = Properties.Strings.TextNoticeText
92 | .Replace("{power_limit}", $"{powerLimit:0}")
93 | .Replace("{actual_power_limit}", $"{hardwareMonitor.CpuPackagePower:0.00}");
94 |
95 | var noticeText = $@"{Properties.Settings.Default.CurrentMode}
96 | {powerLimitText}
97 | CPU: {hardwareMonitor.CpuUsage:0}%、{hardwareMonitor.CpuTemperature:0}℃、{hardwareMonitor.CpuFreq:0}MHz,GPU: {hardwareMonitor.VideoCard3DUsage:0}%";
98 | if (noticeText.Length >= 64)
99 | {
100 | noticeText = noticeText.Substring(0, 63);
101 | }
102 |
103 | return noticeText;
104 | }
105 |
106 | public static string GetModeDetailText(string mode)
107 | {
108 | return $"{Properties.Strings.ResourceManager.GetString(mode)}-{GetPowerLimitByMode(mode)}W";
109 | }
110 | }
111 | }
--------------------------------------------------------------------------------
/Common/Processor/AMDProcessor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using RyzenTuner.Common.Container;
3 |
4 | namespace RyzenTuner.Common.Processor
5 | {
6 | public class AmdProcessor
7 | {
8 | public enum PowerType
9 | {
10 | // long
11 | Slow = 0,
12 | Stapm = 1,
13 | Fast = 2,
14 | }
15 |
16 | private readonly IntPtr _ry;
17 | private readonly bool _canChangeTdp;
18 |
19 | public AmdProcessor()
20 | {
21 | try
22 | {
23 | _ry = RyzenAdj.init_ryzenadj();
24 | if (_ry == IntPtr.Zero)
25 | {
26 | throw new Exception("init ryzenadj failed");
27 | }
28 |
29 | var family = RyzenAdj.get_cpu_family(_ry);
30 |
31 | switch (family)
32 | {
33 | case RyzenFamily.FamUnknown:
34 | case RyzenFamily.FamEnd:
35 | default:
36 | _canChangeTdp = false;
37 | break;
38 |
39 | case RyzenFamily.FamRaven:
40 | case RyzenFamily.FamPicasso:
41 | case RyzenFamily.FamDali:
42 | case RyzenFamily.FamRenoir:
43 | case RyzenFamily.FamLucienne:
44 | case RyzenFamily.FamCezanne:
45 | case RyzenFamily.FamVangogh:
46 | case RyzenFamily.FamRembrandt:
47 | _canChangeTdp = true;
48 | break;
49 | }
50 |
51 | }
52 | catch (DllNotFoundException ex)
53 | {
54 | throw new Exception($"Failed to load libryzenadj.dll: {ex.Message}", ex);
55 | }
56 | catch (BadImageFormatException ex)
57 | {
58 | throw new Exception($"libryzenadj.dll architecture mismatch (32/64-bit?)", ex);
59 | }
60 | catch (Exception ex)
61 | {
62 | throw new Exception($"init ryzenadj failed: {ex.Message}", ex);
63 | }
64 | }
65 |
66 | ///
67 | /// 返回 stamp limit 数据。
68 | ///
69 | /// 备注:
70 | /// 该方法在部分 CPU 下会返回 NULL
71 | ///
72 | /// 说明:
73 | /// 测试处理器: AMD Ryzen™ 7 PRO 6850HS
74 | /// 测试 RyzenAdj 方法:get_tctl_temp、get_fast_limit、get_slow_limit、get_stapm_limit
75 | /// 返回结果:NaN
76 | ///
77 | ///
78 | ///
79 | public float GetStampLimit()
80 | {
81 | return RyzenAdj.get_stapm_limit(_ry);
82 | }
83 |
84 |
85 | public bool SetTctlTemp(uint temp)
86 | {
87 | var result = RyzenAdj.set_tctl_temp(_ry, temp);
88 | return result == (int)ErrCode.AdjErrNone;
89 | }
90 |
91 | private bool SetTdpLimit(PowerType type, double limit)
92 | {
93 | if (!_canChangeTdp)
94 | {
95 | return false;
96 | }
97 |
98 | // 例如:15W : 15000 mW
99 | limit *= 1000;
100 |
101 | var result = type switch
102 | {
103 | PowerType.Fast => RyzenAdj.set_fast_limit(_ry, (uint)limit),
104 | PowerType.Slow => RyzenAdj.set_slow_limit(_ry, (uint)limit),
105 | PowerType.Stapm => RyzenAdj.set_stapm_limit(_ry, (uint)limit),
106 | _ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
107 | };
108 |
109 | AppContainer.Logger().Debug($"AMDProcessor.SetTdpLimit: type {type}, limit: {(uint)limit}, result: {result}");
110 |
111 | return result == (int)ErrCode.AdjErrNone;
112 | }
113 |
114 | public bool SetFastPPT(double limit)
115 | {
116 | return SetTdpLimit(PowerType.Fast, limit);
117 | }
118 |
119 | public bool SetSlowPPT(double limit)
120 | {
121 | return SetTdpLimit(PowerType.Slow, limit);
122 | }
123 |
124 | public bool SetStampPPT(double limit)
125 | {
126 | return SetTdpLimit(PowerType.Stapm, limit);
127 | }
128 | }
129 | }
--------------------------------------------------------------------------------
/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/Common/Logger/SimpleLogger.cs:
--------------------------------------------------------------------------------
1 | /*
2 | MIT License
3 |
4 | Copyright (c) 2016 Heiswayi Nrird
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 | */
24 |
25 | using System;
26 | using System.Diagnostics;
27 |
28 | namespace RyzenTuner.Common.Logger
29 | {
30 | /**
31 | * Refer: https://gist.github.com/heiswayi/69ef5413c0f28b3a58d964447c275058
32 | */
33 | public class SimpleLogger
34 | {
35 | [Flags]
36 | public enum LogLevel
37 | {
38 | Trace = 0,
39 | Debug,
40 | Info,
41 | Warning,
42 | Error,
43 | Fatal
44 | }
45 |
46 | private const string FileExt = ".log";
47 | private readonly object _fileLock = new();
48 | private readonly string _datetimeFormat;
49 | private readonly string _logFilename;
50 |
51 | public LogLevel DefaultLogLevel;
52 |
53 | ///
54 | /// Initiate an instance of SimpleLogger class constructor.
55 | /// If log file does not exist, it will be created automatically.
56 | ///
57 | public SimpleLogger()
58 | {
59 | _datetimeFormat = "yyyy-MM-dd HH:mm:ss";
60 | _logFilename = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name + FileExt;
61 | DefaultLogLevel = LogLevel.Warning;
62 | }
63 |
64 | public LogLevel ToLogLevel(string logLevel)
65 | {
66 | return logLevel switch
67 | {
68 | "Trace" => LogLevel.Trace,
69 | "Debug" => LogLevel.Debug,
70 | "Info" => LogLevel.Info,
71 | "Warning" => LogLevel.Warning,
72 | "Error" => LogLevel.Error,
73 | "Fatal" => LogLevel.Fatal,
74 | _ => throw new Exception($"不正确的 log level 类型:{logLevel}")
75 | };
76 | }
77 |
78 | ///
79 | /// Log a DEBUG message
80 | ///
81 | /// Message
82 | public void Debug(string text)
83 | {
84 | WriteFormattedLog(LogLevel.Debug, text);
85 | }
86 |
87 | ///
88 | /// Log an ERROR message
89 | ///
90 | /// Message
91 | public void Error(string text)
92 | {
93 | WriteFormattedLog(LogLevel.Error, text);
94 | }
95 |
96 | ///
97 | /// Log a FATAL ERROR message
98 | ///
99 | /// Message
100 | public void Fatal(string text)
101 | {
102 | WriteFormattedLog(LogLevel.Fatal, text);
103 | }
104 |
105 | ///
106 | /// Log an INFO message
107 | ///
108 | /// Message
109 | public void Info(string text)
110 | {
111 | WriteFormattedLog(LogLevel.Info, text);
112 | }
113 |
114 | ///
115 | /// Log a TRACE message
116 | ///
117 | /// Message
118 | public void Trace(string text)
119 | {
120 | WriteFormattedLog(LogLevel.Trace, text);
121 | }
122 |
123 | ///
124 | /// Log a WARNING message
125 | ///
126 | /// Message
127 | public void Warning(string text)
128 | {
129 | WriteFormattedLog(LogLevel.Warning, text);
130 | }
131 |
132 | public void LogException(Exception e)
133 | {
134 | // Get stack trace for the exception with source file information
135 | var st = new StackTrace(e, true);
136 | // Get the top stack frame
137 | var frame = st.GetFrame(0);
138 | // Get the line number from the stack frame
139 | var line = frame.GetFileLineNumber();
140 |
141 | Warning($"Exception: {e.Message}\nLine: {line}\nStackTrace: {st}");
142 | }
143 |
144 | private void WriteLine(string text, bool append = false)
145 | {
146 | if (string.IsNullOrEmpty(text))
147 | {
148 | return;
149 | }
150 |
151 | lock (_fileLock)
152 | {
153 | using (System.IO.StreamWriter writer =
154 | new System.IO.StreamWriter(_logFilename, append, System.Text.Encoding.UTF8))
155 | {
156 | writer.WriteLine(text);
157 | }
158 | }
159 | }
160 |
161 | private void WriteFormattedLog(LogLevel level, string text)
162 | {
163 | if (level < DefaultLogLevel)
164 | {
165 | return;
166 | }
167 |
168 | var pretext = level switch
169 | {
170 | LogLevel.Trace => DateTime.Now.ToString(_datetimeFormat) + " [TRACE] ",
171 | LogLevel.Info => DateTime.Now.ToString(_datetimeFormat) + " [INFO] ",
172 | LogLevel.Debug => DateTime.Now.ToString(_datetimeFormat) + " [DEBUG] ",
173 | LogLevel.Warning => DateTime.Now.ToString(_datetimeFormat) + " [WARNING] ",
174 | LogLevel.Error => DateTime.Now.ToString(_datetimeFormat) + " [ERROR] ",
175 | LogLevel.Fatal => DateTime.Now.ToString(_datetimeFormat) + " [FATAL] ",
176 | _ => ""
177 | };
178 |
179 | WriteLine(pretext + text, true);
180 | }
181 | }
182 | }
--------------------------------------------------------------------------------
/Common/EnergyStar/Interop/Win32Api.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Security;
4 | using System.Text;
5 |
6 | namespace RyzenTuner.Common.EnergyStar.Interop
7 | {
8 | internal class Win32Api
9 | {
10 | [DllImport("kernel32.dll")]
11 | public static extern int GetProcessId(IntPtr handle);
12 |
13 | [DllImport("kernel32.dll", SetLastError = true)]
14 | public static extern bool QueryFullProcessImageName([In] IntPtr hProcess, [In] int dwFlags,
15 | [Out] StringBuilder lpExeName, ref int lpdwSize);
16 |
17 | [DllImport("user32.dll")]
18 | public static extern IntPtr GetForegroundWindow();
19 |
20 | [DllImport("user32.dll", SetLastError = true)]
21 | public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
22 |
23 | [DllImport("kernel32.dll", SetLastError = true)]
24 | public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, uint processId);
25 |
26 |
27 | [DllImport("kernel32.dll", SetLastError = true)]
28 | public static extern bool SetProcessInformation([In] IntPtr hProcess,
29 | [In] PROCESS_INFORMATION_CLASS ProcessInformationClass, IntPtr ProcessInformation,
30 | uint ProcessInformationSize);
31 |
32 | [DllImport("kernel32.dll", SetLastError = true)]
33 | public static extern bool SetPriorityClass(IntPtr handle, PriorityClass priorityClass);
34 |
35 | [DllImport("kernel32.dll", SetLastError = true)]
36 | [SuppressUnmanagedCodeSecurity]
37 | [return: MarshalAs(UnmanagedType.Bool)]
38 | public static extern bool CloseHandle(IntPtr hObject);
39 |
40 | public delegate bool WindowEnumProc(IntPtr hwnd, IntPtr lparam);
41 |
42 | [DllImport("user32.dll")]
43 | [return: MarshalAs(UnmanagedType.Bool)]
44 | public static extern bool EnumChildWindows(IntPtr hwnd, WindowEnumProc callback, IntPtr lParam);
45 |
46 | // We don't need to bloat this app with WinForm/WPF to show a simple message box
47 | [DllImport("user32.dll")]
48 | public static extern int MessageBox(IntPtr hInstance, string lpText, string lpCaption, uint type);
49 |
50 | // two message box releated constants
51 | public const int MB_OK = 0x00000000;
52 | public const int MB_ICONERROR = 0x00000010;
53 |
54 | [Flags]
55 | public enum ProcessAccessFlags : uint
56 | {
57 | All = 0x001F0FFF,
58 | Terminate = 0x00000001,
59 | CreateThread = 0x00000002,
60 | VirtualMemoryOperation = 0x00000008,
61 | VirtualMemoryRead = 0x00000010,
62 | VirtualMemoryWrite = 0x00000020,
63 | DuplicateHandle = 0x00000040,
64 | CreateProcess = 0x000000080,
65 | SetQuota = 0x00000100,
66 | SetInformation = 0x00000200,
67 | QueryInformation = 0x00000400,
68 | QueryLimitedInformation = 0x00001000,
69 | Synchronize = 0x00100000
70 | }
71 |
72 | ///
73 | /// 参考:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ne-processthreadsapi-process_information_class
74 | ///
75 | public enum PROCESS_INFORMATION_CLASS
76 | {
77 | ProcessMemoryPriority,
78 | ProcessMemoryExhaustionInfo,
79 | ProcessAppMemoryInfo,
80 | ProcessInPrivateInfo,
81 |
82 | // The process information is represented by a PROCESS_POWER_THROTTLING_STATE structure.
83 | // Allows applications to configure how the system should throttle the target process’s activity when managing power.
84 | ProcessPowerThrottling,
85 | ProcessReservedValue1,
86 | ProcessTelemetryCoverageInfo,
87 | ProcessProtectionLevelInfo,
88 | ProcessLeapSecondInfo,
89 | ProcessInformationClassMax,
90 | }
91 |
92 | [Flags]
93 | public enum ProcessorPowerThrottlingFlags : uint
94 | {
95 | None = 0x0,
96 |
97 | // 当一个进程设置为 PROCESS_POWER_THROTTLING_EXECUTION_SPEED 时,该进程将被分类为 EcoQoS
98 | // 系统通过对 EcoQoS 进程降低 CPU 频率或使用更多高能效的内核等操作来提高电源效率
99 | // 在 Windows 11 之前,EcoQoS 级别并不存在,进程被标记为 LowQoS
100 | // LowQoS:在电池模式下,选择最有效的CPU频率和调度到高效核心。1709 以后版本可用。
101 | // EcoQos:总是选择最有效的CPU频率,并调度到高效的核心。Windows 11 以后版本可用。
102 | // 参考:
103 | // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setprocessinformation
104 | // https://docs.microsoft.com/en-us/windows/win32/procthread/quality-of-service
105 | PROCESS_POWER_THROTTLING_EXECUTION_SPEED = 0x1,
106 | }
107 |
108 | ///
109 | /// 参考:https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setpriorityclass
110 | ///
111 | public enum PriorityClass : uint
112 | {
113 | // 【实时】具有最高优先级的进程。该进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程
114 | REALTIME_PRIORITY_CLASS = 0x100,
115 |
116 | // 【高】执行必须立即执行的时间关键任务的流程
117 | // 在使用高优先级类时要格外小心,因为高优先级类应用程序几乎可以使用所有可用的CPU时间。
118 | HIGH_PRIORITY_CLASS = 0x80,
119 |
120 | // 【高于正常】优先级高于普通优先级但低于高优先级的进程
121 | ABOVE_NORMAL_PRIORITY_CLASS = 0x8000,
122 |
123 | // 【正常】Process with no special scheduling needs
124 | NORMAL_PRIORITY_CLASS = 0x00000020,
125 |
126 | // 【低于正常】优先级高于空闲优先级但低于正常优先级的进程
127 | BELOW_NORMAL_PRIORITY_CLASS = 0x4000,
128 |
129 | // 【低】仅在系统空闲时才运行线程的进程。进程的线程会被运行在更高优先级类中的任何进程的线程抢占。
130 | // 屏幕保护程序就是一个例子。空闲优先级类由子进程继承
131 | IDLE_PRIORITY_CLASS = 0x00000040,
132 |
133 | // 开始后台处理模式。系统降低了进程(及其线程)的资源调度优先级,以便它可以在不显著影响前台活动的情况下执行后台工作
134 | // PROCESS_MODE_BACKGROUND_BEGIN 不适合用于低优先级的后台工作
135 | // 参考:https://stackoverflow.com/questions/13631644/setthreadpriority-and-setpriorityclass
136 | PROCESS_MODE_BACKGROUND_BEGIN = 0x100000, // Windows Vista/2008 and higher
137 |
138 | // 结束后台处理模式。系统恢复进程(及其线程)进入后台处理模式前的资源调度优先级
139 | PROCESS_MODE_BACKGROUND_END = 0x200000, // Windows Vista/2008 and higher
140 | }
141 |
142 | [StructLayout(LayoutKind.Sequential)]
143 | public struct ProcessPowerThrottlingState
144 | {
145 | public const uint ProcessPowerThrottlingCurrentVersion = 1;
146 |
147 | public uint Version;
148 | public ProcessorPowerThrottlingFlags ControlMask;
149 | public ProcessorPowerThrottlingFlags StateMask;
150 | }
151 | }
152 | }
--------------------------------------------------------------------------------
/UI/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | 17, 17
122 |
123 |
124 | 222, 17
125 |
126 |
127 |
128 | 520, 17
129 |
130 |
--------------------------------------------------------------------------------
/Common/Hardware/HardwareMonitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using LibreHardwareMonitor.Hardware;
5 | using RyzenTuner.Common.Container;
6 |
7 | namespace RyzenTuner.Common.Hardware
8 | {
9 | public class HardwareMonitor
10 | {
11 | private float _cpuUsage;
12 | private float _cpuPackagePower;
13 | private float _cpuTemperature;
14 | private float _cpuFreq;
15 |
16 | private float _videoCard3DUsage;
17 |
18 | private readonly Computer _computer;
19 |
20 | public HardwareMonitor()
21 | {
22 | _computer = new Computer
23 | {
24 | IsCpuEnabled = true,
25 | IsGpuEnabled = true,
26 | IsMemoryEnabled = false,
27 | IsMotherboardEnabled = false,
28 | IsControllerEnabled = false,
29 | IsNetworkEnabled = false,
30 | IsStorageEnabled = false
31 | };
32 |
33 | _computer.Open();
34 | }
35 |
36 | // Finalizers / destructor
37 | ~HardwareMonitor()
38 | {
39 | _computer.Close();
40 | }
41 |
42 | public float CpuUsage => _cpuUsage;
43 |
44 | public float CpuPackagePower => _cpuPackagePower;
45 |
46 | public float CpuTemperature => _cpuTemperature;
47 | public float CpuFreq => _cpuFreq;
48 |
49 | public float VideoCard3DUsage => _videoCard3DUsage;
50 |
51 | private void Update()
52 | {
53 | // Triggers the IVisitor.VisitComputer method for the given observer.
54 | _computer.Accept(new UpdateVisitor());
55 | }
56 |
57 | ///
58 | /// 获取 CPU 传感器信息
59 | ///
60 | /// CPU 名称示例:
61 | /// AMD Ryzen 7 PRO 6850HS with Radeon Graphics
62 | /// AMD Ryzen 7 4800H with Radeon Graphics
63 | ///
64 | /// 备注:如果有多个 CPU,可能会有问题。可忽略,普通电脑一般只有一个 CPU 插槽
65 | ///
66 | ///
67 | private List FetchHardwareCpu()
68 | {
69 | var hardwareCpu = _computer
70 | .Hardware
71 | .Where(i => i.HardwareType == HardwareType.Cpu)
72 | .SelectMany(s => s.Sensors);
73 | var cpuEnumerable = hardwareCpu.ToList();
74 |
75 | return cpuEnumerable;
76 | }
77 |
78 | ///
79 | /// 获取核心显卡的传感器信息
80 | ///
81 | /// 显卡名称示例:AMD Radeon(TM) Graphics
82 | /// 备注:如果是 AMD 核心显卡 + AMD 独立显卡,可能会有问题
83 | ///
84 | ///
85 | private List FetchHardwareVideoCard()
86 | {
87 | var hardwareVideoCard = _computer
88 | .Hardware
89 | .Where(i => i.HardwareType == HardwareType.GpuAmd)
90 | .SelectMany(s => s.Sensors);
91 | var videoCardList = hardwareVideoCard.ToList();
92 |
93 | return videoCardList;
94 | }
95 |
96 | public void Monitor()
97 | {
98 | try
99 | {
100 | Update();
101 |
102 | var cpuSensorList = FetchHardwareCpu();
103 | _cpuUsage = FetchCpuUsage(cpuSensorList);
104 | _cpuPackagePower = FetchCpuPackage(cpuSensorList);
105 | _cpuTemperature = FetchCpuTemperature(cpuSensorList);
106 | _cpuFreq = FetchCpuFreq(cpuSensorList);
107 |
108 | var videoCardSensorList = FetchHardwareVideoCard();
109 | _videoCard3DUsage = FetchVideoCard3DUsage(videoCardSensorList);
110 | }
111 | catch (Exception e)
112 | {
113 | AppContainer.Logger().LogException(e);
114 | }
115 | }
116 |
117 | private float FetchVideoCard3DUsage(IEnumerable videoCardSensorList)
118 | {
119 | var linqVideoCard3D = videoCardSensorList
120 | .Where(s => s.SensorType == SensorType.Load)
121 | .Where(s => s.Name == "D3D 3D")
122 | .Where(s => s.Value != null)
123 | .Select(s => s.Value)
124 | .FirstOrDefault();
125 | if (linqVideoCard3D is <= 100)
126 | {
127 | return linqVideoCard3D.Value;
128 | }
129 |
130 | return 0;
131 | }
132 |
133 | private float FetchCpuTemperature(IEnumerable cpuEnumerable)
134 | {
135 | // CPU 温度
136 | var linqCpuTemperature = cpuEnumerable
137 | .Where(s => s.SensorType == SensorType.Temperature)
138 | .Where(s => s.Name == "Core (Tctl/Tdie)")
139 | .Where(s => s.Value != null)
140 | .Select(s => s.Value)
141 | .FirstOrDefault();
142 | if (linqCpuTemperature is <= 150)
143 | {
144 | return linqCpuTemperature.Value;
145 | }
146 |
147 | return 0;
148 | }
149 |
150 | ///
151 | /// 获取 CPU 功耗
152 | ///
153 | ///
154 | ///
155 | private float FetchCpuPackage(IEnumerable cpuEnumerable)
156 | {
157 | //
158 | var linqCpuPackage = cpuEnumerable
159 | .Where(s => s.SensorType == SensorType.Power)
160 | .Where(s => s.Name == "Package")
161 | .Where(s => s.Value != null)
162 | .Select(s => s.Value)
163 | .FirstOrDefault();
164 | if (linqCpuPackage is <= 1000)
165 | {
166 | return linqCpuPackage.Value;
167 | }
168 |
169 | return 0;
170 | }
171 |
172 | ///
173 | /// 获取 CPU 占用率
174 | ///
175 | ///
176 | ///
177 | private static float FetchCpuUsage(IEnumerable cpuEnumerable)
178 | {
179 | var linqCpuUsage = cpuEnumerable
180 | .Where(s => s.SensorType == SensorType.Load)
181 | .Where(s => s.Name == "CPU Total")
182 | .Where(s => s.Value != null)
183 | .Select(s => s.Value)
184 | .FirstOrDefault();
185 |
186 | if (linqCpuUsage is <= 100)
187 | {
188 | return linqCpuUsage.Value;
189 | }
190 |
191 | return 0;
192 | }
193 |
194 | ///
195 | /// 获取 CPU 平均频率
196 | ///
197 | ///
198 | ///
199 | private float FetchCpuFreq(IEnumerable cpuEnumerable)
200 | {
201 | var cpuCount = Environment.ProcessorCount;
202 |
203 | float tmpTotal = 0;
204 | var tmpCount = 0;
205 |
206 | for (var i = 1; i <= cpuCount; i++)
207 | {
208 | var linqCpuFreq = cpuEnumerable
209 | .Where(s => s.SensorType == SensorType.Clock)
210 | .Where(s => s.Name == $"Core #{i}")
211 | .Where(s => s.Value != null)
212 | .Select(s => s.Value)
213 | .FirstOrDefault();
214 | if (linqCpuFreq is > 100)
215 | {
216 | tmpTotal += linqCpuFreq.Value;
217 | tmpCount++;
218 | }
219 | }
220 |
221 | if (tmpCount <= 0)
222 | {
223 | return 0;
224 | }
225 |
226 | return tmpTotal / tmpCount;
227 | }
228 | }
229 | }
--------------------------------------------------------------------------------
/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | namespace RyzenTuner.Properties {
11 |
12 |
13 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
14 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")]
15 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
16 |
17 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
18 |
19 | public static Settings Default {
20 | get {
21 | return defaultInstance;
22 | }
23 | }
24 |
25 | [global::System.Configuration.UserScopedSettingAttribute()]
26 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
27 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
28 | public bool EnergyStar {
29 | get {
30 | return ((bool)(this["EnergyStar"]));
31 | }
32 | set {
33 | this["EnergyStar"] = value;
34 | }
35 | }
36 |
37 | [global::System.Configuration.UserScopedSettingAttribute()]
38 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
39 | [global::System.Configuration.DefaultSettingValueAttribute("False")]
40 | public bool KeepAwake {
41 | get {
42 | return ((bool)(this["KeepAwake"]));
43 | }
44 | set {
45 | this["KeepAwake"] = value;
46 | }
47 | }
48 |
49 | [global::System.Configuration.UserScopedSettingAttribute()]
50 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
51 | [global::System.Configuration.DefaultSettingValueAttribute("16")]
52 | public string CustomMode {
53 | get {
54 | return ((string)(this["CustomMode"]));
55 | }
56 | set {
57 | this["CustomMode"] = value;
58 | }
59 | }
60 |
61 | [global::System.Configuration.UserScopedSettingAttribute()]
62 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
63 | [global::System.Configuration.DefaultSettingValueAttribute("16")]
64 | public string AutoMode {
65 | get {
66 | return ((string)(this["AutoMode"]));
67 | }
68 | set {
69 | this["AutoMode"] = value;
70 | }
71 | }
72 |
73 | [global::System.Configuration.UserScopedSettingAttribute()]
74 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
75 | [global::System.Configuration.DefaultSettingValueAttribute("8")]
76 | public string SleepMode {
77 | get {
78 | return ((string)(this["SleepMode"]));
79 | }
80 | set {
81 | this["SleepMode"] = value;
82 | }
83 | }
84 |
85 | [global::System.Configuration.UserScopedSettingAttribute()]
86 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
87 | [global::System.Configuration.DefaultSettingValueAttribute("16")]
88 | public string PowerSaveMode {
89 | get {
90 | return ((string)(this["PowerSaveMode"]));
91 | }
92 | set {
93 | this["PowerSaveMode"] = value;
94 | }
95 | }
96 |
97 | [global::System.Configuration.UserScopedSettingAttribute()]
98 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
99 | [global::System.Configuration.DefaultSettingValueAttribute("26")]
100 | public string BalancedMode {
101 | get {
102 | return ((string)(this["BalancedMode"]));
103 | }
104 | set {
105 | this["BalancedMode"] = value;
106 | }
107 | }
108 |
109 | [global::System.Configuration.UserScopedSettingAttribute()]
110 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
111 | [global::System.Configuration.DefaultSettingValueAttribute("45")]
112 | public string PerformanceMode {
113 | get {
114 | return ((string)(this["PerformanceMode"]));
115 | }
116 | set {
117 | this["PerformanceMode"] = value;
118 | }
119 | }
120 |
121 | [global::System.Configuration.UserScopedSettingAttribute()]
122 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
123 | [global::System.Configuration.DefaultSettingValueAttribute("AutoMode")]
124 | public string CurrentMode {
125 | get {
126 | return ((string)(this["CurrentMode"]));
127 | }
128 | set {
129 | this["CurrentMode"] = value;
130 | }
131 | }
132 |
133 | [global::System.Configuration.UserScopedSettingAttribute()]
134 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
135 | [global::System.Configuration.DefaultSettingValueAttribute("Debug")]
136 | public string LogLevel {
137 | get {
138 | return ((string)(this["LogLevel"]));
139 | }
140 | set {
141 | this["LogLevel"] = value;
142 | }
143 | }
144 |
145 | [global::System.Configuration.UserScopedSettingAttribute()]
146 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
147 | [global::System.Configuration.DefaultSettingValueAttribute("example1.exe,example2.exe")]
148 | public string EnergyStarBypassProcessList {
149 | get {
150 | return ((string)(this["EnergyStarBypassProcessList"]));
151 | }
152 | set {
153 | this["EnergyStarBypassProcessList"] = value;
154 | }
155 | }
156 |
157 | [global::System.Configuration.UserScopedSettingAttribute()]
158 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
159 | [global::System.Configuration.DefaultSettingValueAttribute("100")]
160 | public int TctlTemp {
161 | get {
162 | return ((int)(this["TctlTemp"]));
163 | }
164 | set {
165 | this["TctlTemp"] = value;
166 | }
167 | }
168 |
169 | [global::System.Configuration.UserScopedSettingAttribute()]
170 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
171 | [global::System.Configuration.DefaultSettingValueAttribute("51")]
172 | public int FastPPT {
173 | get {
174 | return ((int)(this["FastPPT"]));
175 | }
176 | set {
177 | this["FastPPT"] = value;
178 | }
179 | }
180 |
181 | [global::System.Configuration.UserScopedSettingAttribute()]
182 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
183 | [global::System.Configuration.DefaultSettingValueAttribute("45")]
184 | public int SlowPPT {
185 | get {
186 | return ((int)(this["SlowPPT"]));
187 | }
188 | set {
189 | this["SlowPPT"] = value;
190 | }
191 | }
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/Properties/Strings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | //
5 | // Changes to this file may cause incorrect behavior and will be lost if
6 | // the code is regenerated.
7 | //
8 | //------------------------------------------------------------------------------
9 |
10 | namespace RyzenTuner.Properties {
11 | using System;
12 |
13 |
14 | ///
15 | /// A strongly-typed resource class, for looking up localized strings, etc.
16 | ///
17 | // This class was auto-generated by the StronglyTypedResourceBuilder
18 | // class via a tool like ResGen or Visual Studio.
19 | // To add or remove a member, edit your .ResX file then rerun ResGen
20 | // with the /str option, or rebuild your VS project.
21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
24 | internal class Strings {
25 |
26 | private static global::System.Resources.ResourceManager resourceMan;
27 |
28 | private static global::System.Globalization.CultureInfo resourceCulture;
29 |
30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
31 | internal Strings() {
32 | }
33 |
34 | ///
35 | /// Returns the cached ResourceManager instance used by this class.
36 | ///
37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
38 | internal static global::System.Resources.ResourceManager ResourceManager {
39 | get {
40 | if (object.ReferenceEquals(resourceMan, null)) {
41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("RyzenTuner.Properties.Strings", typeof(Strings).Assembly);
42 | resourceMan = temp;
43 | }
44 | return resourceMan;
45 | }
46 | }
47 |
48 | ///
49 | /// Overrides the current thread's CurrentUICulture property for all
50 | /// resource lookups using this strongly typed resource class.
51 | ///
52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
53 | internal static global::System.Globalization.CultureInfo Culture {
54 | get {
55 | return resourceCulture;
56 | }
57 | set {
58 | resourceCulture = value;
59 | }
60 | }
61 |
62 | ///
63 | /// Looks up a localized string similar to 自动模式.
64 | ///
65 | internal static string AutoMode {
66 | get {
67 | return ResourceManager.GetString("AutoMode", resourceCulture);
68 | }
69 | }
70 |
71 | ///
72 | /// Looks up a localized string similar to 平衡模式.
73 | ///
74 | internal static string BalancedMode {
75 | get {
76 | return ResourceManager.GetString("BalancedMode", resourceCulture);
77 | }
78 | }
79 |
80 | ///
81 | /// Looks up a localized string similar to 手动模式.
82 | ///
83 | internal static string CustomMode {
84 | get {
85 | return ResourceManager.GetString("CustomMode", resourceCulture);
86 | }
87 | }
88 |
89 | ///
90 | /// Looks up a localized string similar to 性能模式.
91 | ///
92 | internal static string PerformanceMode {
93 | get {
94 | return ResourceManager.GetString("PerformanceMode", resourceCulture);
95 | }
96 | }
97 |
98 | ///
99 | /// Looks up a localized string similar to 省电模式.
100 | ///
101 | internal static string PowerSaveMode {
102 | get {
103 | return ResourceManager.GetString("PowerSaveMode", resourceCulture);
104 | }
105 | }
106 |
107 | ///
108 | /// Looks up a localized string similar to 待机模式.
109 | ///
110 | internal static string SleepMode {
111 | get {
112 | return ResourceManager.GetString("SleepMode", resourceCulture);
113 | }
114 | }
115 |
116 | ///
117 | /// Looks up a localized string similar to 关于.
118 | ///
119 | internal static string TextAbout {
120 | get {
121 | return ResourceManager.GetString("TextAbout", resourceCulture);
122 | }
123 | }
124 |
125 | ///
126 | /// Looks up a localized string similar to 开启 EnergyStar.
127 | ///
128 | internal static string TextEnableEnergyStar {
129 | get {
130 | return ResourceManager.GetString("TextEnableEnergyStar", resourceCulture);
131 | }
132 | }
133 |
134 | ///
135 | /// Looks up a localized string similar to 同一时间内,只允许运行一个 RyzenTuner 程序.
136 | ///
137 | internal static string TextExceptionOnlyOneProgramIsAllowedToRun {
138 | get {
139 | return ResourceManager.GetString("TextExceptionOnlyOneProgramIsAllowedToRun", resourceCulture);
140 | }
141 | }
142 |
143 | ///
144 | /// Looks up a localized string similar to RyzenTuner 出现错误.
145 | ///
146 | internal static string TextExceptionTitle {
147 | get {
148 | return ResourceManager.GetString("TextExceptionTitle", resourceCulture);
149 | }
150 | }
151 |
152 | ///
153 | /// Looks up a localized string similar to 退出.
154 | ///
155 | internal static string TextExit {
156 | get {
157 | return ResourceManager.GetString("TextExit", resourceCulture);
158 | }
159 | }
160 |
161 | ///
162 | /// Looks up a localized string similar to 功率:限制{power_limit}W、实际{actual_power_limit}W.
163 | ///
164 | internal static string TextNoticeText {
165 | get {
166 | return ResourceManager.GetString("TextNoticeText", resourceCulture);
167 | }
168 | }
169 |
170 | ///
171 | /// Looks up a localized string similar to 其他选项.
172 | ///
173 | internal static string TextOtherOptions {
174 | get {
175 | return ResourceManager.GetString("TextOtherOptions", resourceCulture);
176 | }
177 | }
178 |
179 | ///
180 | /// Looks up a localized string similar to 功率限制.
181 | ///
182 | internal static string TextPowerLimit {
183 | get {
184 | return ResourceManager.GetString("TextPowerLimit", resourceCulture);
185 | }
186 | }
187 |
188 | ///
189 | /// Looks up a localized string similar to 保持唤醒.
190 | ///
191 | internal static string TextStayAwake {
192 | get {
193 | return ResourceManager.GetString("TextStayAwake", resourceCulture);
194 | }
195 | }
196 | }
197 | }
198 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Ww][Ii][Nn]32/
27 | [Aa][Rr][Mm]/
28 | [Aa][Rr][Mm]64/
29 | bld/
30 | [Bb]in/
31 | [Oo]bj/
32 | [Oo]ut/
33 | [Ll]og/
34 | [Ll]ogs/
35 |
36 | # Visual Studio 2015/2017 cache/options directory
37 | .vs/
38 | # Uncomment if you have tasks that create the project's static files in wwwroot
39 | #wwwroot/
40 |
41 | # Visual Studio 2017 auto generated files
42 | Generated\ Files/
43 |
44 | # MSTest test Results
45 | [Tt]est[Rr]esult*/
46 | [Bb]uild[Ll]og.*
47 |
48 | # NUnit
49 | *.VisualState.xml
50 | TestResult.xml
51 | nunit-*.xml
52 |
53 | # Build Results of an ATL Project
54 | [Dd]ebugPS/
55 | [Rr]eleasePS/
56 | dlldata.c
57 |
58 | # Benchmark Results
59 | BenchmarkDotNet.Artifacts/
60 |
61 | # .NET Core
62 | project.lock.json
63 | project.fragment.lock.json
64 | artifacts/
65 |
66 | # ASP.NET Scaffolding
67 | ScaffoldingReadMe.txt
68 |
69 | # StyleCop
70 | StyleCopReport.xml
71 |
72 | # Files built by Visual Studio
73 | *_i.c
74 | *_p.c
75 | *_h.h
76 | *.ilk
77 | *.meta
78 | *.obj
79 | *.iobj
80 | *.pch
81 | *.pdb
82 | *.ipdb
83 | *.pgc
84 | *.pgd
85 | *.rsp
86 | *.sbr
87 | *.tlb
88 | *.tli
89 | *.tlh
90 | *.tmp
91 | *.tmp_proj
92 | *_wpftmp.csproj
93 | *.log
94 | *.vspscc
95 | *.vssscc
96 | .builds
97 | *.pidb
98 | *.svclog
99 | *.scc
100 |
101 | # Chutzpah Test files
102 | _Chutzpah*
103 |
104 | # Visual C++ cache files
105 | ipch/
106 | *.aps
107 | *.ncb
108 | *.opendb
109 | *.opensdf
110 | *.sdf
111 | *.cachefile
112 | *.VC.db
113 | *.VC.VC.opendb
114 |
115 | # Visual Studio profiler
116 | *.psess
117 | *.vsp
118 | *.vspx
119 | *.sap
120 |
121 | # Visual Studio Trace Files
122 | *.e2e
123 |
124 | # TFS 2012 Local Workspace
125 | $tf/
126 |
127 | # Guidance Automation Toolkit
128 | *.gpState
129 |
130 | # ReSharper is a .NET coding add-in
131 | _ReSharper*/
132 | *.[Rr]e[Ss]harper
133 | *.DotSettings.user
134 |
135 | # TeamCity is a build add-in
136 | _TeamCity*
137 |
138 | # DotCover is a Code Coverage Tool
139 | *.dotCover
140 |
141 | # AxoCover is a Code Coverage Tool
142 | .axoCover/*
143 | !.axoCover/settings.json
144 |
145 | # Coverlet is a free, cross platform Code Coverage Tool
146 | coverage*.json
147 | coverage*.xml
148 | coverage*.info
149 |
150 | # Visual Studio code coverage results
151 | *.coverage
152 | *.coveragexml
153 |
154 | # NCrunch
155 | _NCrunch_*
156 | .*crunch*.local.xml
157 | nCrunchTemp_*
158 |
159 | # MightyMoose
160 | *.mm.*
161 | AutoTest.Net/
162 |
163 | # Web workbench (sass)
164 | .sass-cache/
165 |
166 | # Installshield output folder
167 | [Ee]xpress/
168 |
169 | # DocProject is a documentation generator add-in
170 | DocProject/buildhelp/
171 | DocProject/Help/*.HxT
172 | DocProject/Help/*.HxC
173 | DocProject/Help/*.hhc
174 | DocProject/Help/*.hhk
175 | DocProject/Help/*.hhp
176 | DocProject/Help/Html2
177 | DocProject/Help/html
178 |
179 | # Click-Once directory
180 | publish/
181 |
182 | # Publish Web Output
183 | *.[Pp]ublish.xml
184 | *.azurePubxml
185 | # Note: Comment the next line if you want to checkin your web deploy settings,
186 | # but database connection strings (with potential passwords) will be unencrypted
187 | *.pubxml
188 | *.publishproj
189 |
190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
191 | # checkin your Azure Web App publish settings, but sensitive information contained
192 | # in these scripts will be unencrypted
193 | PublishScripts/
194 |
195 | # NuGet Packages
196 | *.nupkg
197 | # NuGet Symbol Packages
198 | *.snupkg
199 | # The packages folder can be ignored because of Package Restore
200 | **/[Pp]ackages/*
201 | # except build/, which is used as an MSBuild target.
202 | !**/[Pp]ackages/build/
203 | # Uncomment if necessary however generally it will be regenerated when needed
204 | #!**/[Pp]ackages/repositories.config
205 | # NuGet v3's project.json files produces more ignorable files
206 | *.nuget.props
207 | *.nuget.targets
208 |
209 | # Microsoft Azure Build Output
210 | csx/
211 | *.build.csdef
212 |
213 | # Microsoft Azure Emulator
214 | ecf/
215 | rcf/
216 |
217 | # Windows Store app package directories and files
218 | AppPackages/
219 | BundleArtifacts/
220 | Package.StoreAssociation.xml
221 | _pkginfo.txt
222 | *.appx
223 | *.appxbundle
224 | *.appxupload
225 |
226 | # Visual Studio cache files
227 | # files ending in .cache can be ignored
228 | *.[Cc]ache
229 | # but keep track of directories ending in .cache
230 | !?*.[Cc]ache/
231 |
232 | # Others
233 | ClientBin/
234 | ~$*
235 | *~
236 | *.dbmdl
237 | *.dbproj.schemaview
238 | *.jfm
239 | *.pfx
240 | *.publishsettings
241 | orleans.codegen.cs
242 |
243 | # Including strong name files can present a security risk
244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
245 | #*.snk
246 |
247 | # Since there are multiple workflows, uncomment next line to ignore bower_components
248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
249 | #bower_components/
250 |
251 | # RIA/Silverlight projects
252 | Generated_Code/
253 |
254 | # Backup & report files from converting an old project file
255 | # to a newer Visual Studio version. Backup files are not needed,
256 | # because we have git ;-)
257 | _UpgradeReport_Files/
258 | Backup*/
259 | UpgradeLog*.XML
260 | UpgradeLog*.htm
261 | ServiceFabricBackup/
262 | *.rptproj.bak
263 |
264 | # SQL Server files
265 | *.mdf
266 | *.ldf
267 | *.ndf
268 |
269 | # Business Intelligence projects
270 | *.rdl.data
271 | *.bim.layout
272 | *.bim_*.settings
273 | *.rptproj.rsuser
274 | *- [Bb]ackup.rdl
275 | *- [Bb]ackup ([0-9]).rdl
276 | *- [Bb]ackup ([0-9][0-9]).rdl
277 |
278 | # Microsoft Fakes
279 | FakesAssemblies/
280 |
281 | # GhostDoc plugin setting file
282 | *.GhostDoc.xml
283 |
284 | # Node.js Tools for Visual Studio
285 | .ntvs_analysis.dat
286 | node_modules/
287 |
288 | # Visual Studio 6 build log
289 | *.plg
290 |
291 | # Visual Studio 6 workspace options file
292 | *.opt
293 |
294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
295 | *.vbw
296 |
297 | # Visual Studio LightSwitch build output
298 | **/*.HTMLClient/GeneratedArtifacts
299 | **/*.DesktopClient/GeneratedArtifacts
300 | **/*.DesktopClient/ModelManifest.xml
301 | **/*.Server/GeneratedArtifacts
302 | **/*.Server/ModelManifest.xml
303 | _Pvt_Extensions
304 |
305 | # Paket dependency manager
306 | .paket/paket.exe
307 | paket-files/
308 |
309 | # FAKE - F# Make
310 | .fake/
311 |
312 | # CodeRush personal settings
313 | .cr/personal
314 |
315 | # Python Tools for Visual Studio (PTVS)
316 | __pycache__/
317 | *.pyc
318 |
319 | # Cake - Uncomment if you are using it
320 | # tools/**
321 | # !tools/packages.config
322 |
323 | # Tabs Studio
324 | *.tss
325 |
326 | # Telerik's JustMock configuration file
327 | *.jmconfig
328 |
329 | # BizTalk build output
330 | *.btp.cs
331 | *.btm.cs
332 | *.odx.cs
333 | *.xsd.cs
334 |
335 | # OpenCover UI analysis results
336 | OpenCover/
337 |
338 | # Azure Stream Analytics local run output
339 | ASALocalRun/
340 |
341 | # MSBuild Binary and Structured Log
342 | *.binlog
343 |
344 | # NVidia Nsight GPU debugger configuration file
345 | *.nvuser
346 |
347 | # MFractors (Xamarin productivity tool) working folder
348 | .mfractor/
349 |
350 | # Local History for Visual Studio
351 | .localhistory/
352 |
353 | # BeatPulse healthcheck temp database
354 | healthchecksdb
355 |
356 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
357 | MigrationBackup/
358 |
359 | # Ionide (cross platform F# VS Code tools) working folder
360 | .ionide/
361 |
362 | # Fody - auto-generated XML schema
363 | FodyWeavers.xsd
364 |
365 | .idea
366 | .DS_Store
367 | RyzenTuner.csproj.DotSettings
--------------------------------------------------------------------------------
/UI/MainForm.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 | using RyzenTuner.Common;
4 | using RyzenTuner.Common.Container;
5 | using RyzenTuner.Properties;
6 | using RyzenTuner.Utils;
7 |
8 | namespace RyzenTuner.UI
9 | {
10 | public partial class MainForm : Form
11 | {
12 | private Int64 _tickCount;
13 |
14 | public MainForm()
15 | {
16 | InitializeComponent();
17 | }
18 |
19 | private void Form1_Load(object sender, EventArgs e)
20 | {
21 | checkBoxEnergyStar.Checked = Properties.Settings.Default.EnergyStar;
22 | keepAwakeCheckBox.Checked = Properties.Settings.Default.KeepAwake;
23 | textBox1.Text = Properties.Settings.Default.CustomMode;
24 | SyncEnergyModeSelection();
25 |
26 | // 设置系统唤醒状态
27 | keepAwakeCheckBox_CheckedChanged(null, EventArgs.Empty);
28 |
29 | WindowState = FormWindowState.Minimized;
30 | }
31 |
32 | private void checkBoxEnergyStar_CheckedChanged(object sender, EventArgs e)
33 | {
34 | Properties.Settings.Default.EnergyStar = checkBoxEnergyStar.Checked;
35 | Properties.Settings.Default.Save();
36 |
37 | if (checkBoxEnergyStar.Checked)
38 | {
39 | _needRunBoostAllBgProcesses = false;
40 | }
41 | else
42 | {
43 | _needRunBoostAllBgProcesses = true;
44 | }
45 | }
46 |
47 | private void keepAwakeCheckBox_CheckedChanged(object? sender, EventArgs e)
48 | {
49 | Properties.Settings.Default.KeepAwake = keepAwakeCheckBox.Checked;
50 | Properties.Settings.Default.Save();
51 |
52 | if (Properties.Settings.Default.KeepAwake)
53 | {
54 | Awake.KeepingSysAwake(true);
55 | }
56 | else
57 | {
58 | Awake.AllowSysSleep();
59 | }
60 | }
61 |
62 | private void AboutAppToolStripMenuItem_Click(object sender, EventArgs e)
63 | {
64 | new AboutForm().ShowDialog();
65 | }
66 |
67 | private void ExitAppToolStripMenuItem_Click(object sender, EventArgs e)
68 | {
69 | Application.Exit();
70 | }
71 |
72 | private void Form1_FormClosing(object sender, FormClosingEventArgs e)
73 | {
74 | if (e.CloseReason == CloseReason.UserClosing)
75 | {
76 | if (radioButton6.Checked)
77 | {
78 | ChangeEnergyMode(radioButton6, e);
79 | }
80 |
81 | e.Cancel = true;
82 | Hide();
83 | }
84 | }
85 |
86 | private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
87 | {
88 | Show();
89 | }
90 |
91 | private void mainFormTimer_Tick(object sender, EventArgs e)
92 | {
93 | _tickCount++;
94 | AppContainer.HardwareMonitor().Monitor();
95 |
96 | DoPowerLimit();
97 |
98 | DoProcessManage();
99 | }
100 |
101 |
102 | private void ChangeEnergyMode(object sender, EventArgs e)
103 | {
104 | if (((RadioButton)sender).Checked)
105 | {
106 | var checkedMode = ((RadioButton)sender).Tag.ToString();
107 | Settings.Default.CurrentMode = checkedMode;
108 | Settings.Default.Save();
109 | SyncEnergyModeSelection();
110 |
111 | DoPowerLimit();
112 | }
113 | }
114 |
115 | private void DoPowerLimit()
116 | {
117 | try
118 | {
119 | notifyIcon1.Text = RyzenTunerUtils.GetNoticeText();
120 | var processor = AppContainer.AmdProcessor();
121 |
122 | var stampLimit = RyzenAdjUtils.GetPowerLimit();
123 | var tctlTemp = RyzenAdjUtils.GetTctlTemp();
124 | var fastPpt = Settings.Default.FastPPT;
125 | var slowPpt = Settings.Default.SlowPPT;
126 |
127 | AppContainer.Logger().Debug($"fastPPT: {fastPpt}, slowPPT: {slowPpt}, stampPPT: {stampLimit}, tctlTemp: {tctlTemp}");
128 |
129 | // 调用 ryzenadj 调整 Cpu 设置
130 | // 说明:
131 | // 假设 fastPPT 为 51 瓦,slowPPT 为 45 瓦,stampPPT 为 30 瓦。
132 | // 假设没有撞到功耗墙
133 | // 当打开网页的时候,处理器功耗会升到 51 瓦(fastPPT 定义)
134 | // 过了 x 秒后(由 SLOW PPT TIME CONSTANT定义) ,处理器功耗变为 45 瓦(slowPPT 定义)
135 | // 再过了 x 后秒(由 STAPM TIME CONSTANT 定义),处理器功耗变为 30 瓦(stampPPT 定义)
136 | // 之后,一直维持在 30 瓦
137 |
138 | // 备注:
139 | // ryzenadj 0.17.0 以及部分旧版本测试在当前环境存在问题:
140 | // 1、stamp limit 设置不生效
141 | // 2、调整 fast limit,会同时修改 fast limit 和 stamp limit
142 | // 因此,设置 fastPPT 的值跟 stamp 一样
143 | // 这样子的话,前期不会有性能爆发,在后面会有一段性能爆发
144 | processor.SetFastPPT(stampLimit);
145 | processor.SetSlowPPT(slowPpt);
146 | processor.SetStampPPT(stampLimit);
147 |
148 | AppContainer.AmdProcessor().SetTctlTemp((uint)tctlTemp);
149 |
150 | // 配置系统电源计划
151 | // 1、仅在【性能模式】下开启睿频
152 | if (RyzenTunerUtils.IsPerformanceMode(stampLimit))
153 | {
154 | AppContainer.PowerConfig().EnableCpuBoost();
155 | }
156 | else
157 | {
158 | AppContainer.PowerConfig().DisableCpuBoost();
159 | }
160 | }
161 | catch (Exception e)
162 | {
163 | MessageBox.Show(e.Message);
164 | radioButton5.Checked = true;
165 | ChangeEnergyMode(radioButton5, EventArgs.Empty);
166 | }
167 | }
168 |
169 | ///
170 | /// 执行进程管理任务(EnergyStar)
171 | ///
172 | private void DoProcessManage()
173 | {
174 | // 如果开启【EnergyStar】
175 | if (checkBoxEnergyStar.Checked)
176 | {
177 | AppContainer.EnergyManager().HandleForeground();
178 |
179 | // Throttle 当前用户的所有后台进程
180 | if (
181 | // 首次运行 30 秒
182 | _tickCount == 15 ||
183 | // 每 5 分钟
184 | _tickCount % 150 == 0
185 | )
186 | {
187 | AppContainer.EnergyManager().ThrottleAllUserBackgroundProcesses();
188 | }
189 |
190 | return;
191 | }
192 |
193 | // 关闭【EnergyStar】的情况
194 | if (_needRunBoostAllBgProcesses)
195 | {
196 | // Boost 当前用户的所有后台进程:每 5 分钟检查一次,一般只运行一次
197 | if (_tickCount % 150 == 0)
198 | {
199 | AppContainer.EnergyManager().BoostAllUserBackgroundProcesses();
200 | _needRunBoostAllBgProcesses = false;
201 | }
202 | }
203 | }
204 |
205 | private void SyncEnergyModeSelection()
206 | {
207 | foreach (Control c in powerLimitGroupBox.Controls)
208 | {
209 | if (c.Tag != null && c.Tag.ToString() == Properties.Settings.Default.CurrentMode)
210 | {
211 | var rb = (RadioButton)c;
212 | rb.Checked = true;
213 | }
214 | }
215 |
216 |
217 | foreach (ToolStripItem tsmi in contextMenuStrip1.Items)
218 | {
219 | if (tsmi.Tag != null && tsmi.Tag.ToString() == Properties.Settings.Default.CurrentMode)
220 | {
221 | var tsmi2 = (ToolStripMenuItem)tsmi;
222 | tsmi2.Checked = true;
223 | }
224 | else if (tsmi is ToolStripMenuItem)
225 | {
226 | var tsmi2 = (ToolStripMenuItem)tsmi;
227 | tsmi2.Checked = false;
228 | }
229 | }
230 | }
231 |
232 | private void textBox1_TextChanged(object sender, EventArgs e)
233 | {
234 | if (radioButton6.Checked) radioButton5.Checked = true;
235 | Properties.Settings.Default.CustomMode = textBox1.Text;
236 | Properties.Settings.Default.Save();
237 | }
238 |
239 | private void ToolStripMenuItems_Clicked(object sender, EventArgs e)
240 | {
241 | var menuItem = (ToolStripMenuItem)sender;
242 | if (menuItem.CheckState != CheckState.Checked)
243 | {
244 | menuItem.Checked = true;
245 | }
246 |
247 | // 根据用户点击的托盘菜单选项,自动选中不同的【功率限制】按钮
248 | foreach (Control c in powerLimitGroupBox.Controls)
249 | {
250 | if (c.Tag == null || c.Tag.ToString() != ((ToolStripMenuItem)sender).Tag.ToString())
251 | {
252 | continue;
253 | }
254 |
255 | var radioButton = (RadioButton)c;
256 | radioButton.Checked = true;
257 | }
258 | }
259 |
260 | private void Form1_Shown(object sender, EventArgs e)
261 | {
262 | if (Environment.GetCommandLineArgs().Length > 1 && Environment.GetCommandLineArgs()[1] == "-hide")
263 | {
264 | Hide();
265 | }
266 | }
267 | }
268 | }
--------------------------------------------------------------------------------
/RyzenTuner.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {EBC428A6-134E-4B8B-8B89-3595FF804785}
8 | WinExe
9 | RyzenTuner
10 | RyzenTuner
11 | v4.8
12 | 512
13 | true
14 | true
15 | 9
16 | enable
17 |
18 |
19 | AnyCPU
20 | none
21 | true
22 | bin\Release\
23 | TRACE
24 | prompt
25 | 4
26 | false
27 |
28 |
29 | bin\Debug\
30 | full
31 | true
32 | false
33 |
34 |
35 | app.manifest
36 |
37 |
38 | Resources\phoenix-96.ico
39 |
40 |
41 |
42 | packages\HidSharp.2.1.0\lib\net35\HidSharp.dll
43 |
44 |
45 | packages\LibreHardwareMonitorLib.0.9.0\lib\net47\LibreHardwareMonitorLib.dll
46 |
47 |
48 |
49 |
50 | packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll
51 |
52 |
53 |
54 |
55 |
56 |
57 | packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll
58 |
59 |
60 |
61 | packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll
62 |
63 |
64 | packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | packages\Vanara.Core.3.4.6\lib\net48\Vanara.Core.dll
77 |
78 |
79 | packages\Vanara.PInvoke.Kernel32.3.4.6\lib\net48\Vanara.PInvoke.Kernel32.dll
80 |
81 |
82 | packages\Vanara.PInvoke.PowrProf.3.4.6\lib\net48\Vanara.PInvoke.PowrProf.dll
83 |
84 |
85 | packages\Vanara.PInvoke.Shared.3.4.6\lib\net48\Vanara.PInvoke.Shared.dll
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | True
104 | True
105 | Strings.resx
106 |
107 |
108 | Form
109 |
110 |
111 | AboutForm.cs
112 |
113 |
114 | Form
115 |
116 |
117 | MainForm.cs
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 | Resources.resx
126 |
127 |
128 | ResXFileCodeGenerator
129 | Resources.Designer.cs
130 | Designer
131 |
132 |
133 | True
134 | Resources.resx
135 |
136 |
137 | Strings.resx
138 |
139 |
140 | ResXFileCodeGenerator
141 | Strings.Designer.cs
142 |
143 |
144 | AboutForm.cs
145 |
146 |
147 | AboutForm.cs
148 |
149 |
150 | MainForm.cs
151 |
152 |
153 | MainForm.cs
154 |
155 |
156 |
157 |
158 | SettingsSingleFileGenerator
159 | Settings.Designer.cs
160 |
161 |
162 | True
163 | Settings.settings
164 | True
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | False
173 | Microsoft .NET Framework 4.8 %28x86 和 x64%29
174 | true
175 |
176 |
177 | False
178 | .NET Framework 3.5 SP1
179 | false
180 |
181 |
182 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/Common/Processor/RyzenAdj.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 |
4 | namespace RyzenTuner.Common.Processor
5 | {
6 | // 参考:https://github.com/FlyGoat/RyzenAdj/blob/master/lib/ryzenadj.h#L15-L26
7 | public enum RyzenFamily
8 | {
9 | FamUnknown = -1,
10 | FamRaven = 0,
11 | FamPicasso,
12 | FamRenoir,
13 | FamCezanne,
14 | FamDali,
15 | FamLucienne,
16 | FamVangogh,
17 | FamRembrandt,
18 | FamEnd
19 | }
20 |
21 | // 错误码,参考:https://github.com/FlyGoat/RyzenAdj/blob/master/lib/ryzenadj.h#L52-L56
22 | public enum ErrCode
23 | {
24 | AdjErrNone = 0,
25 | AdjErrFamUnsupported = -1,
26 | AdjErrSmuTimeout = -2,
27 | AdjErrSmuUnsupported = -3,
28 | AdjErrSmuRejected = -4,
29 | AdjErrMemoryAccess = -5,
30 | }
31 |
32 | /**
33 | * RyzenAdj.cs
34 | * Author:Valkirie
35 | * Refer:https://github.com/Valkirie/ControllerService/blob/main/ControllerCommon/Processor/AMD/RyzenAdj.cs
36 | *
37 | * 依赖:
38 | * inpoutx64.dll
39 | * libryzenadj.dll
40 | * WinRing0x64.dll
41 | * WinRing0x64.sys
42 | *
43 | * 当前 ryzenadj 版本:v0.17.0
44 | */
45 | public class RyzenAdj
46 | {
47 | [DllImport("libryzenadj.dll")]
48 | public static extern IntPtr init_ryzenadj();
49 |
50 | [DllImport("libryzenadj.dll")]
51 | public static extern int set_stapm_limit(IntPtr ry, [In] uint value);
52 |
53 | [DllImport("libryzenadj.dll")]
54 | public static extern int set_fast_limit(IntPtr ry, [In] uint value);
55 |
56 | [DllImport("libryzenadj.dll")]
57 | public static extern int set_slow_limit(IntPtr ry, [In] uint value);
58 |
59 | [DllImport("libryzenadj.dll")]
60 | public static extern int set_slow_time(IntPtr ry, [In] uint value);
61 |
62 | [DllImport("libryzenadj.dll")]
63 | public static extern int set_stapm_time(IntPtr ry, [In] uint value);
64 |
65 | [DllImport("libryzenadj.dll")]
66 | public static extern int set_tctl_temp(IntPtr ry, [In] uint value);
67 |
68 | [DllImport("libryzenadj.dll")]
69 | public static extern int set_vrm_current(IntPtr ry, [In] uint value);
70 |
71 | [DllImport("libryzenadj.dll")]
72 | public static extern int set_vrmsoc_current(IntPtr ry, [In] uint value);
73 |
74 | [DllImport("libryzenadj.dll")]
75 | public static extern int set_vrmmax_current(IntPtr ry, [In] uint value);
76 |
77 | [DllImport("libryzenadj.dll")]
78 | public static extern int set_vrmsocmax_current(IntPtr ry, [In] uint value);
79 |
80 | [DllImport("libryzenadj.dll")]
81 | public static extern int set_psi0_current(IntPtr ry, [In] uint value);
82 |
83 | [DllImport("libryzenadj.dll")]
84 | public static extern int set_psi0soc_current(IntPtr ry, [In] uint value);
85 |
86 | [DllImport("libryzenadj.dll")]
87 | public static extern int set_max_gfxclk_freq(IntPtr ry, [In] uint value);
88 |
89 | [DllImport("libryzenadj.dll")]
90 | public static extern int set_min_gfxclk_freq(IntPtr ry, [In] uint value);
91 |
92 | [DllImport("libryzenadj.dll")]
93 | public static extern int set_max_socclk_freq(IntPtr ry, [In] uint value);
94 |
95 | [DllImport("libryzenadj.dll")]
96 | public static extern int set_min_socclk_freq(IntPtr ry, [In] uint value);
97 |
98 | [DllImport("libryzenadj.dll")]
99 | public static extern int set_max_fclk_freq(IntPtr ry, [In] uint value);
100 |
101 | [DllImport("libryzenadj.dll")]
102 | public static extern int set_min_fclk_freq(IntPtr ry, [In] uint value);
103 |
104 | [DllImport("libryzenadj.dll")]
105 | public static extern int set_max_vcn(IntPtr ry, [In] uint value);
106 |
107 | [DllImport("libryzenadj.dll")]
108 | public static extern int set_min_vcn(IntPtr ry, [In] uint value);
109 |
110 | [DllImport("libryzenadj.dll")]
111 | public static extern int set_max_lclk(IntPtr ry, [In] uint value);
112 |
113 | [DllImport("libryzenadj.dll")]
114 | public static extern int set_min_lclk(IntPtr ry, [In] uint value);
115 |
116 | [DllImport("libryzenadj.dll")]
117 | public static extern int set_gfx_clk(IntPtr ry, [In] uint value);
118 |
119 | [DllImport("libryzenadj.dll")]
120 | public static extern int set_oc_clk(IntPtr ry, [In] uint value);
121 |
122 | [DllImport("libryzenadj.dll")]
123 | public static extern int set_per_core_oc_clk(IntPtr ry, [In] uint value);
124 |
125 | [DllImport("libryzenadj.dll")]
126 | public static extern int set_oc_volt(IntPtr ry, [In] uint value);
127 |
128 | [DllImport("libryzenadj.dll")]
129 | public static extern int disable_oc(IntPtr ry);
130 |
131 | [DllImport("libryzenadj.dll")]
132 | public static extern int enable_oc(IntPtr ry);
133 |
134 | [DllImport("libryzenadj.dll")]
135 | public static extern int set_prochot_deassertion_ramp(IntPtr ry, [In] uint value);
136 |
137 | [DllImport("libryzenadj.dll")]
138 | public static extern int set_apu_skin_temp_limit(IntPtr ry, [In] uint value);
139 |
140 | [DllImport("libryzenadj.dll")]
141 | public static extern int set_dgpu_skin_temp_limit(IntPtr ry, [In] uint value);
142 |
143 | [DllImport("libryzenadj.dll")]
144 | public static extern int set_apu_slow_limit(IntPtr ry, [In] uint value);
145 |
146 | [DllImport("libryzenadj.dll")]
147 | public static extern int set_power_saving(IntPtr ry);
148 |
149 | [DllImport("libryzenadj.dll")]
150 | public static extern int set_max_performance(IntPtr ry);
151 |
152 | [DllImport("libryzenadj.dll")]
153 | public static extern int refresh_table(IntPtr ry);
154 |
155 | [DllImport("libryzenadj.dll")]
156 | public static extern IntPtr get_table_values(IntPtr ry);
157 |
158 | [DllImport("libryzenadj.dll")]
159 | public static extern float get_stapm_limit(IntPtr ry);
160 |
161 | [DllImport("libryzenadj.dll")]
162 | public static extern float get_stapm_value(IntPtr ry);
163 |
164 | [DllImport("libryzenadj.dll")]
165 | public static extern float get_stapm_time(IntPtr ry);
166 |
167 | [DllImport("libryzenadj.dll")]
168 | public static extern float get_fast_limit(IntPtr ry);
169 |
170 | [DllImport("libryzenadj.dll")]
171 | public static extern float get_fast_value(IntPtr ry);
172 |
173 | [DllImport("libryzenadj.dll")]
174 | public static extern float get_slow_limit(IntPtr ry);
175 |
176 | [DllImport("libryzenadj.dll")]
177 | public static extern float get_slow_value(IntPtr ry);
178 |
179 | [DllImport("libryzenadj.dll")]
180 | public static extern float get_apu_slow_limit(IntPtr ry);
181 |
182 | [DllImport("libryzenadj.dll")]
183 | public static extern float get_apu_slow_value(IntPtr ry);
184 |
185 | [DllImport("libryzenadj.dll")]
186 | public static extern float get_vrm_current(IntPtr ry);
187 |
188 | [DllImport("libryzenadj.dll")]
189 | public static extern float get_vrm_current_value(IntPtr ry);
190 |
191 | [DllImport("libryzenadj.dll")]
192 | public static extern float get_vrmsoc_current(IntPtr ry);
193 |
194 | [DllImport("libryzenadj.dll")]
195 | public static extern float get_vrmsoc_current_value(IntPtr ry);
196 |
197 | [DllImport("libryzenadj.dll")]
198 | public static extern float get_vrmmax_current(IntPtr ry);
199 |
200 | [DllImport("libryzenadj.dll")]
201 | public static extern float get_vrmmax_current_value(IntPtr ry);
202 |
203 | [DllImport("libryzenadj.dll")]
204 | public static extern float get_vrmsocmax_current(IntPtr ry);
205 |
206 | [DllImport("libryzenadj.dll")]
207 | public static extern float get_vrmsocmax_current_value(IntPtr ry);
208 |
209 | [DllImport("libryzenadj.dll")]
210 | public static extern float get_tctl_temp(IntPtr ry);
211 |
212 | [DllImport("libryzenadj.dll")]
213 | public static extern float get_tctl_temp_value(IntPtr ry);
214 |
215 | [DllImport("libryzenadj.dll")]
216 | public static extern float get_apu_skin_temp_limit(IntPtr ry);
217 |
218 | [DllImport("libryzenadj.dll")]
219 | public static extern float get_apu_skin_temp_value(IntPtr ry);
220 |
221 | [DllImport("libryzenadj.dll")]
222 | public static extern float get_dgpu_skin_temp_limit(IntPtr ry);
223 |
224 | [DllImport("libryzenadj.dll")]
225 | public static extern float get_dgpu_skin_temp_value(IntPtr ry);
226 |
227 | [DllImport("libryzenadj.dll")]
228 | public static extern float get_core_clk(IntPtr ry, uint value);
229 |
230 | [DllImport("libryzenadj.dll")]
231 | public static extern float get_core_temp(IntPtr ry, uint value);
232 |
233 | [DllImport("libryzenadj.dll")]
234 | public static extern float get_core_power(IntPtr ry, uint value);
235 |
236 | [DllImport("libryzenadj.dll")]
237 | public static extern float get_core_volt(IntPtr ry, uint value);
238 |
239 | [DllImport("libryzenadj.dll")]
240 | public static extern float get_l3_logic(IntPtr ry);
241 |
242 | [DllImport("libryzenadj.dll")]
243 | public static extern float get_l3_vddm(IntPtr ry);
244 |
245 | [DllImport("libryzenadj.dll")]
246 | public static extern float get_l3_temp(IntPtr ry);
247 |
248 | [DllImport("libryzenadj.dll")]
249 | public static extern float get_l3_clk(IntPtr ry);
250 |
251 | [DllImport("libryzenadj.dll")]
252 | public static extern float get_gfx_clk(IntPtr ry);
253 |
254 | [DllImport("libryzenadj.dll")]
255 | public static extern float get_gfx_temp(IntPtr ry);
256 |
257 | [DllImport("libryzenadj.dll")]
258 | public static extern float get_gfx_volt(IntPtr ry);
259 |
260 | [DllImport("libryzenadj.dll")]
261 | public static extern float get_mem_clk(IntPtr ry);
262 |
263 | [DllImport("libryzenadj.dll")]
264 | public static extern float get_fclk(IntPtr ry);
265 |
266 | [DllImport("libryzenadj.dll")]
267 | public static extern float get_soc_power(IntPtr ry);
268 |
269 | [DllImport("libryzenadj.dll")]
270 | public static extern float get_soc_volt(IntPtr ry);
271 |
272 | [DllImport("libryzenadj.dll")]
273 | public static extern float get_socket_power(IntPtr ry);
274 |
275 | [DllImport("libryzenadj.dll")]
276 | public static extern RyzenFamily get_cpu_family(IntPtr ry);
277 | }
278 | }
--------------------------------------------------------------------------------
/docs/AMD_Ryzen7_6850HS.md:
--------------------------------------------------------------------------------
1 | ## 目的
2 |
3 | 了解 CPU 在日常待机情况下的数据,方便 RyzenTuner 配置合适的参数。
4 |
5 | ## 基本信息
6 |
7 | 1. 测试 CPU:AMD Ryzen™ 7 PRO 6850HS
8 | * TDP:35W
9 | * 基础频率:3.2GHz
10 | * 最大加速时钟频率:4.7GHz
11 | * 最高温度:95 ℃
12 | 2.
13 | 测试代码:[DebugUtils.cs#L12-L23](https://github.com/zqhong/RyzenTuner/blob/1af00263b1222fdaa9e6a2e1016c2954d65e0d5a/Utils/DebugUtils.cs#L12-L23)
14 | 3. 室温 26 ℃
15 |
16 | ## 待机
17 |
18 | ### 测试内容
19 |
20 | 1. 后台运行日常软件,比如微信、Chrome、终端
21 | 2. 前台运行 IDE
22 |
23 | ### 关闭睿频
24 |
25 | ```text
26 | 功率:限制1瓦、实际4.28瓦,CPU:19.12%、51.88℃、399.27MHz,GPU:2.87%
27 | 功率:限制2瓦、实际4.36瓦,CPU:29.95%、50.88℃、399.27MHz,GPU:5.80%
28 | 功率:限制3瓦、实际4.07瓦,CPU:16.84%、50.13℃、399.27MHz,GPU:2.75%
29 | 功率:限制4瓦、实际4.06瓦,CPU:6.63%、49.63℃、1343.98MHz,GPU:2.25%
30 | 功率:限制5瓦、实际4.57瓦,CPU:3.50%、49.25℃、1397.45MHz,GPU:2.35%
31 | 功率:限制6瓦、实际5.63瓦,CPU:3.58%、49.13℃、1397.45MHz,GPU:2.61%
32 | 功率:限制7瓦、实际6.92瓦,CPU:2.41%、49.25℃、2720.04MHz,GPU:2.13%
33 | 功率:限制8瓦、实际7.62瓦,CPU:0.71%、49.75℃、3169.22MHz,GPU:1.84%
34 | 功率:限制9瓦、实际7.66瓦,CPU:0.72%、49.88℃、3169.22MHz,GPU:1.72%
35 | 功率:限制10瓦、实际7.64瓦,CPU:0.71%、49.88℃、3169.22MHz,GPU:1.76%
36 | 功率:限制11瓦、实际7.68瓦,CPU:1.09%、49.88℃、3169.22MHz,GPU:1.71%
37 | 功率:限制12瓦、实际7.66瓦,CPU:0.85%、50.00℃、3169.22MHz,GPU:1.79%
38 | 功率:限制13瓦、实际7.61瓦,CPU:0.66%、49.88℃、3169.22MHz,GPU:1.75%
39 | 功率:限制14瓦、实际7.64瓦,CPU:0.66%、50.00℃、3169.22MHz,GPU:1.90%
40 | 功率:限制15瓦、实际7.72瓦,CPU:0.95%、50.00℃、3169.22MHz,GPU:1.78%
41 | 功率:限制16瓦、实际7.64瓦,CPU:0.85%、50.00℃、3169.22MHz,GPU:1.67%
42 | 功率:限制17瓦、实际7.62瓦,CPU:0.70%、50.00℃、3169.22MHz,GPU:1.77%
43 | 功率:限制18瓦、实际7.67瓦,CPU:0.71%、50.13℃、3169.22MHz,GPU:1.83%
44 | 功率:限制19瓦、实际7.64瓦,CPU:0.95%、50.13℃、3169.22MHz,GPU:1.75%
45 | 功率:限制20瓦、实际7.59瓦,CPU:1.10%、50.00℃、3169.22MHz,GPU:1.76%
46 | 功率:限制21瓦、实际7.73瓦,CPU:0.90%、50.00℃、3169.22MHz,GPU:1.68%
47 | 功率:限制22瓦、实际7.72瓦,CPU:1.57%、50.00℃、3169.22MHz,GPU:1.99%
48 | 功率:限制23瓦、实际7.66瓦,CPU:0.72%、50.00℃、3169.22MHz,GPU:1.75%
49 | 功率:限制24瓦、实际7.67瓦,CPU:0.67%、50.00℃、3169.22MHz,GPU:1.73%
50 | 功率:限制25瓦、实际7.62瓦,CPU:0.71%、50.13℃、3169.22MHz,GPU:1.74%
51 | 功率:限制26瓦、实际7.62瓦,CPU:0.76%、50.13℃、3169.22MHz,GPU:1.75%
52 | 功率:限制27瓦、实际7.71瓦,CPU:1.18%、50.13℃、3169.22MHz,GPU:1.81%
53 | 功率:限制28瓦、实际7.80瓦,CPU:0.90%、50.38℃、3169.22MHz,GPU:1.93%
54 | 功率:限制29瓦、实际7.73瓦,CPU:0.71%、50.25℃、3169.22MHz,GPU:1.80%
55 | 功率:限制30瓦、实际7.60瓦,CPU:0.57%、50.25℃、3169.22MHz,GPU:1.78%
56 | ```
57 |
58 | ### 开启睿频
59 |
60 | ```text
61 | 功率:限制1瓦、实际4.26瓦,CPU:19.17%、49.50℃、399.27MHz,GPU:3.33%
62 | 功率:限制2瓦、实际3.98瓦,CPU:17.43%、48.88℃、399.27MHz,GPU:2.76%
63 | 功率:限制3瓦、实际3.99瓦,CPU:16.78%、48.38℃、399.27MHz,GPU:2.77%
64 | 功率:限制4瓦、实际4.04瓦,CPU:7.57%、48.13℃、1397.45MHz,GPU:2.71%
65 | 功率:限制5瓦、实际4.53瓦,CPU:2.75%、48.00℃、1397.45MHz,GPU:2.53%
66 | 功率:限制6瓦、实际5.73瓦,CPU:3.34%、48.00℃、1397.45MHz,GPU:2.20%
67 | 功率:限制7瓦、实际6.94瓦,CPU:2.15%、48.13℃、1597.09MHz,GPU:2.18%
68 | 功率:限制8瓦、实际8.35瓦,CPU:0.95%、49.00℃、2670.13MHz,GPU:1.91%
69 | 功率:限制9瓦、实际9.39瓦,CPU:1.00%、49.88℃、3437.48MHz,GPU:2.04%
70 | 功率:限制10瓦、实际10.38瓦,CPU:0.72%、50.88℃、3169.22MHz,GPU:1.90%
71 | 功率:限制11瓦、实际11.33瓦,CPU:0.47%、51.63℃、3654.79MHz,GPU:1.84%
72 | 功率:限制12瓦、实际11.76瓦,CPU:0.95%、52.50℃、3169.22MHz,GPU:1.82%
73 | 功率:限制13瓦、实际12.02瓦,CPU:0.75%、53.13℃、3169.22MHz,GPU:1.94%
74 | 功率:限制14瓦、实际12.28瓦,CPU:0.95%、53.88℃、3169.22MHz,GPU:1.83%
75 | 功率:限制15瓦、实际12.18瓦,CPU:0.71%、54.13℃、3169.22MHz,GPU:2.01%
76 | 功率:限制16瓦、实际12.19瓦,CPU:0.66%、54.25℃、3169.22MHz,GPU:1.91%
77 | 功率:限制17瓦、实际12.53瓦,CPU:0.66%、54.63℃、3358.45MHz,GPU:2.05%
78 | 功率:限制18瓦、实际12.55瓦,CPU:0.80%、54.88℃、3169.22MHz,GPU:1.86%
79 | 功率:限制19瓦、实际12.69瓦,CPU:0.90%、55.13℃、3169.22MHz,GPU:1.98%
80 | 功率:限制20瓦、实际12.55瓦,CPU:0.56%、55.38℃、3093.31MHz,GPU:1.84%
81 | 功率:限制21瓦、实际12.57瓦,CPU:0.67%、55.75℃、3169.22MHz,GPU:1.93%
82 | 功率:限制22瓦、实际12.42瓦,CPU:0.76%、55.88℃、3164.02MHz,GPU:1.93%
83 | 功率:限制23瓦、实际12.62瓦,CPU:0.95%、56.13℃、3169.22MHz,GPU:1.96%
84 | 功率:限制24瓦、实际13.01瓦,CPU:0.66%、56.50℃、4071.74MHz,GPU:1.84%
85 | 功率:限制25瓦、实际12.89瓦,CPU:0.62%、56.63℃、3363.65MHz,GPU:1.85%
86 | 功率:限制26瓦、实际12.95瓦,CPU:0.43%、56.75℃、3169.22MHz,GPU:1.88%
87 | 功率:限制27瓦、实际12.71瓦,CPU:1.04%、56.88℃、3169.22MHz,GPU:2.05%
88 | 功率:限制28瓦、实际12.50瓦,CPU:0.95%、56.88℃、3169.22MHz,GPU:1.97%
89 | 功率:限制29瓦、实际12.52瓦,CPU:0.62%、57.00℃、3680.78MHz,GPU:1.96%
90 | 功率:限制30瓦、实际12.66瓦,CPU:1.23%、57.13℃、3358.46MHz,GPU:1.95%
91 | ```
92 |
93 | ## 轻度使用
94 |
95 | ### 测试内容
96 |
97 | 1. 播放哔哩哔哩 1080P
98 | 高码率视频:[https://www.bilibili.com/video/BV11V4y1J7Rm](https://www.bilibili.com/video/BV11V4y1J7Rm)
99 | 2. 开启弹幕,智能云屏蔽:3级
100 |
101 | ### 关闭睿频
102 |
103 | ```text
104 | 功率:限制1瓦、实际4.97瓦,CPU:49.02%、49.63℃、399.27MHz,GPU:7.26%
105 | 功率:限制2瓦、实际4.92瓦,CPU:50.70%、48.63℃、399.27MHz,GPU:9.86%
106 | 功率:限制3瓦、实际4.91瓦,CPU:58.71%、47.88℃、399.27MHz,GPU:12.65%
107 | 功率:限制4瓦、实际4.75瓦,CPU:54.32%、47.38℃、399.27MHz,GPU:10.22%
108 | 功率:限制5瓦、实际5.14瓦,CPU:50.99%、47.13℃、476.47MHz,GPU:11.07%
109 | 功率:限制6瓦、实际5.66瓦,CPU:13.21%、47.00℃、1397.45MHz,GPU:7.76%
110 | 功率:限制7瓦、实际6.64瓦,CPU:4.65%、46.88℃、1430.72MHz,GPU:6.06%
111 | 功率:限制8瓦、实际7.94瓦,CPU:6.89%、47.00℃、3169.22MHz,GPU:5.53%
112 | 功率:限制9瓦、实际8.42瓦,CPU:2.30%、47.38℃、3169.22MHz,GPU:4.74%
113 | 功率:限制10瓦、实际8.60瓦,CPU:2.37%、47.63℃、3119.31MHz,GPU:4.66%
114 | 功率:限制11瓦、实际9.25瓦,CPU:4.31%、48.00℃、3169.22MHz,GPU:7.42%
115 | 功率:限制12瓦、实际10.04瓦,CPU:5.40%、48.63℃、3169.22MHz,GPU:11.52%
116 | 功率:限制13瓦、实际9.65瓦,CPU:4.15%、48.75℃、3169.22MHz,GPU:11.06%
117 | 功率:限制14瓦、实际9.44瓦,CPU:3.98%、48.88℃、3169.22MHz,GPU:11.36%
118 | 功率:限制15瓦、实际10.17瓦,CPU:4.68%、49.38℃、3169.22MHz,GPU:11.36%
119 | 功率:限制16瓦、实际8.82瓦,CPU:2.62%、49.25℃、3169.22MHz,GPU:6.16%
120 | 功率:限制17瓦、实际9.90瓦,CPU:3.36%、49.75℃、3169.22MHz,GPU:10.97%
121 | 功率:限制18瓦、实际9.82瓦,CPU:4.29%、50.00℃、3169.22MHz,GPU:10.58%
122 | 功率:限制19瓦、实际9.24瓦,CPU:2.98%、50.25℃、3169.22MHz,GPU:9.25%
123 | 功率:限制20瓦、实际9.15瓦,CPU:3.48%、50.38℃、3169.22MHz,GPU:4.71%
124 | 功率:限制21瓦、实际8.70瓦,CPU:2.70%、50.50℃、3169.22MHz,GPU:4.83%
125 | 功率:限制22瓦、实际9.03瓦,CPU:2.82%、50.75℃、3169.22MHz,GPU:4.83%
126 | 功率:限制23瓦、实际9.09瓦,CPU:4.07%、51.00℃、3169.22MHz,GPU:4.54%
127 | 功率:限制24瓦、实际8.93瓦,CPU:3.13%、51.00℃、3169.22MHz,GPU:6.14%
128 | 功率:限制25瓦、实际9.98瓦,CPU:4.79%、51.13℃、3169.22MHz,GPU:11.21%
129 | 功率:限制26瓦、实际9.66瓦,CPU:4.63%、51.00℃、3169.22MHz,GPU:10.97%
130 | 功率:限制27瓦、实际9.15瓦,CPU:3.84%、50.75℃、3169.22MHz,GPU:6.48%
131 | 功率:限制28瓦、实际8.57瓦,CPU:3.20%、50.38℃、3169.22MHz,GPU:4.57%
132 | 功率:限制29瓦、实际8.76瓦,CPU:3.38%、50.25℃、3169.22MHz,GPU:4.71%
133 | 功率:限制30瓦、实际8.50瓦,CPU:2.43%、50.00℃、3169.22MHz,GPU:4.69%
134 | ```
135 |
136 | ### 开启睿频
137 |
138 | ```text
139 | 功率:限制1瓦、实际4.50瓦,CPU:24.81%、49.13℃、399.27MHz,GPU:8.85%
140 | 功率:限制2瓦、实际4.37瓦,CPU:27.98%、48.25℃、399.27MHz,GPU:8.38%
141 | 功率:限制3瓦、实际4.30瓦,CPU:27.54%、47.75℃、399.27MHz,GPU:8.11%
142 | 功率:限制4瓦、实际4.30瓦,CPU:18.23%、47.25℃、456.64MHz,GPU:8.32%
143 | 功率:限制5瓦、实际4.81瓦,CPU:10.70%、47.00℃、1397.45MHz,GPU:6.44%
144 | 功率:限制6瓦、实际5.52瓦,CPU:7.10%、46.75℃、1397.45MHz,GPU:6.58%
145 | 功率:限制7瓦、实际6.72瓦,CPU:4.41%、46.75℃、1756.80MHz,GPU:6.13%
146 | 功率:限制8瓦、实际7.89瓦,CPU:3.94%、47.38℃、3234.10MHz,GPU:5.13%
147 | 功率:限制9瓦、实际9.32瓦,CPU:4.32%、48.38℃、2036.91MHz,GPU:5.07%
148 | 功率:限制10瓦、实际10.30瓦,CPU:3.39%、49.25℃、3690.14MHz,GPU:4.72%
149 | 功率:限制11瓦、实际11.37瓦,CPU:2.70%、50.50℃、3169.22MHz,GPU:5.23%
150 | 功率:限制12瓦、实际12.39瓦,CPU:2.58%、51.75℃、3040.29MHz,GPU:4.95%
151 | 功率:限制13瓦、实际13.34瓦,CPU:2.77%、53.00℃、3169.22MHz,GPU:5.02%
152 | 功率:限制14瓦、实际14.30瓦,CPU:3.03%、54.38℃、3270.08MHz,GPU:5.02%
153 | 功率:限制15瓦、实际14.90瓦,CPU:2.86%、55.25℃、3535.22MHz,GPU:5.06%
154 | 功率:限制16瓦、实际14.90瓦,CPU:2.62%、55.88℃、3654.79MHz,GPU:4.82%
155 | 功率:限制17瓦、实际15.34瓦,CPU:2.08%、56.63℃、3340.78MHz,GPU:4.96%
156 | 功率:限制18瓦、实际15.08瓦,CPU:2.58%、57.00℃、3169.22MHz,GPU:4.78%
157 | 功率:限制19瓦、实际17.49瓦,CPU:3.05%、58.38℃、3169.22MHz,GPU:5.00%
158 | 功率:限制20瓦、实际15.14瓦,CPU:3.01%、58.13℃、3556.01MHz,GPU:4.54%
159 | 功率:限制21瓦、实际16.50瓦,CPU:3.27%、58.75℃、4041.58MHz,GPU:4.84%
160 | 功率:限制22瓦、实际15.32瓦,CPU:4.28%、58.63℃、3169.22MHz,GPU:4.74%
161 | 功率:限制23瓦、实际15.30瓦,CPU:3.27%、58.63℃、3714.06MHz,GPU:4.94%
162 | 功率:限制24瓦、实际16.21瓦,CPU:3.38%、59.00℃、4148.68MHz,GPU:4.89%
163 | 功率:限制25瓦、实际15.29瓦,CPU:1.85%、58.75℃、3169.22MHz,GPU:4.63%
164 | 功率:限制26瓦、实际15.44瓦,CPU:2.77%、58.75℃、3864.82MHz,GPU:4.75%
165 | 功率:限制27瓦、实际14.94瓦,CPU:2.75%、58.63℃、2975.82MHz,GPU:4.57%
166 | 功率:限制28瓦、实际14.70瓦,CPU:2.37%、58.63℃、3714.06MHz,GPU:4.71%
167 | 功率:限制29瓦、实际14.59瓦,CPU:2.67%、58.50℃、3753.57MHz,GPU:4.71%
168 | 功率:限制30瓦、实际17.01瓦,CPU:4.29%、59.63℃、3169.22MHz,GPU:4.78%
169 | ```
170 |
171 | ## CPU 满载使用
172 |
173 | ### 测试内容
174 |
175 | 1. AIDA64 运行 Stress FPU
176 |
177 | ### 关闭睿频
178 |
179 | ```text
180 | 功率:限制1瓦、实际5.76瓦,CPU:100.00%、52.50℃、399.27MHz,GPU:3.36%
181 | 功率:限制2瓦、实际5.29瓦,CPU:100.00%、51.13℃、399.27MHz,GPU:4.37%
182 | 功率:限制3瓦、实际5.30瓦,CPU:100.00%、50.13℃、399.27MHz,GPU:6.30%
183 | 功率:限制4瓦、实际5.40瓦,CPU:99.96%、49.50℃、399.27MHz,GPU:7.12%
184 | 功率:限制5瓦、实际5.39瓦,CPU:99.96%、49.00℃、399.27MHz,GPU:4.89%
185 | 功率:限制6瓦、实际5.97瓦,CPU:100.00%、48.88℃、608.63MHz,GPU:3.03%
186 | 功率:限制7瓦、实际7.00瓦,CPU:100.00%、49.00℃、835.97MHz,GPU:2.35%
187 | 功率:限制8瓦、实际8.01瓦,CPU:100.00%、49.38℃、998.18MHz,GPU:2.24%
188 | 功率:限制9瓦、实际9.03瓦,CPU:100.00%、49.88℃、1183.56MHz,GPU:2.11%
189 | 功率:限制10瓦、实际9.93瓦,CPU:100.00%、50.50℃、1397.45MHz,GPU:2.10%
190 | 功率:限制11瓦、实际10.69瓦,CPU:100.00%、50.75℃、1397.45MHz,GPU:2.63%
191 | 功率:限制12瓦、实际10.89瓦,CPU:100.00%、50.88℃、1397.45MHz,GPU:2.31%
192 | 功率:限制13瓦、实际12.57瓦,CPU:100.00%、51.25℃、1397.45MHz,GPU:2.11%
193 | 功率:限制14瓦、实际13.80瓦,CPU:100.00%、52.00℃、1637.01MHz,GPU:2.01%
194 | 功率:限制15瓦、实际15.03瓦,CPU:100.00%、52.88℃、1816.69MHz,GPU:2.13%
195 | 功率:限制16瓦、实际16.04瓦,CPU:100.00%、53.88℃、2096.18MHz,GPU:2.42%
196 | 功率:限制17瓦、实际17.04瓦,CPU:100.00%、54.88℃、2220.95MHz,GPU:2.11%
197 | 功率:限制18瓦、实际18.03瓦,CPU:100.00%、55.88℃、2320.77MHz,GPU:2.04%
198 | 功率:限制19瓦、实际19.04瓦,CPU:100.00%、57.00℃、2345.72MHz,GPU:1.80%
199 | 功率:限制20瓦、实际20.05瓦,CPU:100.00%、58.13℃、2445.54MHz,GPU:1.81%
200 | 功率:限制21瓦、实际21.04瓦,CPU:100.00%、59.25℃、2420.58MHz,GPU:1.93%
201 | 功率:限制22瓦、实际22.05瓦,CPU:100.00%、60.50℃、2470.49MHz,GPU:1.83%
202 | 功率:限制23瓦、实际23.05瓦,CPU:100.00%、61.75℃、2676.37MHz,GPU:1.94%
203 | 功率:限制24瓦、实际24.04瓦,CPU:100.00%、62.88℃、2735.63MHz,GPU:2.00%
204 | 功率:限制25瓦、实际25.05瓦,CPU:100.00%、64.25℃、2695.08MHz,GPU:2.02%
205 | 功率:限制26瓦、实际26.06瓦,CPU:100.00%、65.63℃、2869.76MHz,GPU:1.76%
206 | 功率:限制27瓦、实际27.06瓦,CPU:100.00%、67.00℃、2900.96MHz,GPU:1.87%
207 | 功率:限制28瓦、实际28.05瓦,CPU:100.00%、68.25℃、2944.63MHz,GPU:2.00%
208 | 功率:限制29瓦、实际29.08瓦,CPU:100.00%、69.63℃、3022.61MHz,GPU:1.85%
209 | 功率:限制30瓦、实际30.07瓦,CPU:100.00%、71.00℃、3069.40MHz,GPU:2.05%
210 | ```
211 |
212 | ### 开启睿频
213 |
214 | ```text
215 | 功率:限制1瓦、实际6.15瓦,CPU:100.00%、63.75℃、399.27MHz,GPU:3.09%
216 | 功率:限制2瓦、实际5.58瓦,CPU:100.00%、59.88℃、399.27MHz,GPU:3.00%
217 | 功率:限制3瓦、实际5.54瓦,CPU:100.00%、57.63℃、399.27MHz,GPU:3.35%
218 | 功率:限制4瓦、实际5.54瓦,CPU:100.00%、56.13℃、399.27MHz,GPU:3.31%
219 | 功率:限制5瓦、实际5.47瓦,CPU:100.00%、55.13℃、399.27MHz,GPU:3.02%
220 | 功率:限制6瓦、实际5.94瓦,CPU:100.00%、54.25℃、543.18MHz,GPU:2.97%
221 | 功率:限制7瓦、实际7.00瓦,CPU:100.00%、53.88℃、736.16MHz,GPU:2.52%
222 | 功率:限制8瓦、实际8.01瓦,CPU:100.00%、53.75℃、998.53MHz,GPU:2.34%
223 | 功率:限制9瓦、实际8.96瓦,CPU:100.00%、53.88℃、1212.07MHz,GPU:2.09%
224 | 功率:限制10瓦、实际9.99瓦,CPU:100.00%、54.25℃、1397.45MHz,GPU:2.05%
225 | 功率:限制11瓦、实际10.72瓦,CPU:100.00%、54.25℃、1397.45MHz,GPU:2.25%
226 | 功率:限制12瓦、实际10.96瓦,CPU:100.00%、54.13℃、1397.45MHz,GPU:2.88%
227 | 功率:限制13瓦、实际12.28瓦,CPU:100.00%、54.13℃、1397.45MHz,GPU:1.94%
228 | 功率:限制14瓦、实际13.86瓦,CPU:100.00%、54.63℃、1617.05MHz,GPU:1.99%
229 | 功率:限制15瓦、实际15.00瓦,CPU:100.00%、55.25℃、1696.90MHz,GPU:1.90%
230 | 功率:限制16瓦、实际16.03瓦,CPU:100.00%、56.00℃、1976.39MHz,GPU:1.95%
231 | 功率:限制17瓦、实际17.03瓦,CPU:100.00%、56.75℃、2171.04MHz,GPU:2.10%
232 | 功率:限制18瓦、实际18.03瓦,CPU:100.00%、57.63℃、2245.90MHz,GPU:1.89%
233 | 功率:限制19瓦、实际19.03瓦,CPU:100.00%、58.50℃、2270.86MHz,GPU:1.90%
234 | 功率:限制20瓦、实际20.04瓦,CPU:100.00%、59.50℃、2470.49MHz,GPU:1.94%
235 | 功率:限制21瓦、实际21.05瓦,CPU:100.00%、60.50℃、2470.49MHz,GPU:1.81%
236 | 功率:限制22瓦、实际22.06瓦,CPU:100.00%、61.63℃、2573.43MHz,GPU:1.77%
237 | 功率:限制23瓦、实际23.04瓦,CPU:100.00%、62.75℃、2695.08MHz,GPU:1.93%
238 | 功率:限制24瓦、实际24.06瓦,CPU:100.00%、64.00℃、2720.04MHz,GPU:1.96%
239 | 功率:限制25瓦、实际25.06瓦,CPU:100.00%、65.13℃、2819.86MHz,GPU:1.81%
240 | 功率:限制26瓦、实际26.06瓦,CPU:100.00%、66.50℃、2863.53MHz,GPU:1.92%
241 | 功率:限制27瓦、实际27.06瓦,CPU:100.00%、67.63℃、2894.72MHz,GPU:2.01%
242 | 功率:限制28瓦、实际28.07瓦,CPU:100.00%、68.88℃、2969.58MHz,GPU:1.96%
243 | 功率:限制29瓦、实际29.07瓦,CPU:100.00%、70.13℃、2994.54MHz,GPU:1.85%
244 | 功率:限制30瓦、实际30.05瓦,CPU:100.00%、71.50℃、2894.72MHz,GPU:1.90%
245 | ```
246 |
--------------------------------------------------------------------------------
/Common/Container/Container.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT License.
3 | // Refer: https://github.com/microsoft/MinIoC/blob/main/Container.cs
4 |
5 | using System;
6 | using System.Collections.Concurrent;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Linq.Expressions;
10 | using System.Reflection;
11 |
12 | namespace RyzenTuner.Common.Container
13 | {
14 | ///
15 | /// Inversion of control container handles dependency injection for registered types
16 | ///
17 | public class Container : Container.IScope
18 | {
19 | #region Public interfaces
20 |
21 | ///
22 | /// Represents a scope in which per-scope objects are instantiated a single time
23 | ///
24 | public interface IScope : IDisposable, IServiceProvider
25 | {
26 | }
27 |
28 | ///
29 | /// IRegisteredType is return by Container.Register and allows further configuration for the registration
30 | ///
31 | public interface IRegisteredType
32 | {
33 | ///
34 | /// Make registered type a singleton
35 | ///
36 | void AsSingleton();
37 |
38 | ///
39 | /// Make registered type a per-scope type (single instance within a Scope)
40 | ///
41 | void PerScope();
42 | }
43 |
44 | #endregion
45 |
46 | // Map of registered types
47 | private readonly Dictionary> _registeredTypes =
48 | new Dictionary>();
49 |
50 | // Lifetime management
51 | private readonly ContainerLifetime _lifetime;
52 |
53 | ///
54 | /// Creates a new instance of IoC Container
55 | ///
56 | public Container() => _lifetime = new ContainerLifetime(t => _registeredTypes[t]);
57 |
58 | ///
59 | /// Registers a factory function which will be called to resolve the specified interface
60 | ///
61 | /// Interface to register
62 | /// Factory function
63 | ///
64 | public IRegisteredType Register(Type @interface, Func