Skip to content

Commit

Permalink
Set EcoQoS level for background process on Windows
Browse files Browse the repository at this point in the history
The CL sets EcoQoS level for background process which would select
efficient CPU frequency and schedule the process to efficient cores if
available. EcoQoS has been supported since Windows 11.

Bug: 1401383
Change-Id: Ieea0647457574c2394dec615f789f90e062d6e64
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4086121
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
Commit-Queue: Zheda Chen <zheda.chen@intel.com>
Reviewed-by: Francois Pierre Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1084851}
  • Loading branch information
rafaelzch authored and Chromium LUCI CQ committed Dec 19, 2022
1 parent 2a0eaa1 commit 2808be7
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 4 deletions.
8 changes: 6 additions & 2 deletions base/process/process.h
Expand Up @@ -20,9 +20,9 @@
#include <lib/zx/process.h>
#endif

#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS)
#if BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
#include "base/feature_list.h"
#endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS)
#endif // BUILDFLAG(IS_APPLE) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_APPLE)
#include "base/process/port_provider_mac.h"
Expand All @@ -42,6 +42,10 @@ BASE_DECLARE_FEATURE(kMacAllowBackgroundingProcesses);
BASE_EXPORT BASE_DECLARE_FEATURE(kOneGroupPerRenderer);
#endif

#if BUILDFLAG(IS_WIN)
BASE_EXPORT BASE_DECLARE_FEATURE(kUseEcoQoSForBackgroundProcess);
#endif

// Provides a move-only encapsulation of a process.
//
// This object is not tied to the lifetime of the underlying process: the
Expand Down
34 changes: 34 additions & 0 deletions base/process/process_win.cc
Expand Up @@ -11,6 +11,7 @@
#include "base/process/kill.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/base_tracing.h"
#include "base/win/windows_version.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

#include <windows.h>
Expand All @@ -28,6 +29,15 @@ DWORD kBasicProcessAccess =

namespace base {

// Sets Eco QoS (Quality of Service) level for background process which would
// select efficient CPU frequency and schedule the process to efficient cores
// (available on hybrid CPUs).
// QoS is a scheduling Win API which indicates the desired performance and power
// efficiency of a process/thread. EcoQoS is introduced since Windows 11.
BASE_FEATURE(kUseEcoQoSForBackgroundProcess,
"UseEcoQoSForBackgroundProcess",
FEATURE_DISABLED_BY_DEFAULT);

Process::Process(ProcessHandle handle)
: process_(handle), is_current_process_(false) {
CHECK_NE(handle, ::GetCurrentProcess());
Expand Down Expand Up @@ -266,6 +276,30 @@ bool Process::SetProcessBackgrounded(bool value) {
DCHECK(!is_current());
const DWORD priority = value ? IDLE_PRIORITY_CLASS : NORMAL_PRIORITY_CLASS;

if (base::win::OSInfo::GetInstance()->version() >=
base::win::Version::WIN11 &&
FeatureList::IsEnabled(kUseEcoQoSForBackgroundProcess)) {
PROCESS_POWER_THROTTLING_STATE power_throttling;
RtlZeroMemory(&power_throttling, sizeof(power_throttling));
power_throttling.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;

if (value) {
// Sets Eco QoS level.
power_throttling.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
power_throttling.StateMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED;
} else {
// Uses system default.
power_throttling.ControlMask = 0;
power_throttling.StateMask = 0;
}
bool ret =
::SetProcessInformation(Handle(), ProcessPowerThrottling,
&power_throttling, sizeof(power_throttling));
if (ret == 0) {
DPLOG(ERROR) << "Setting process QoS policy fails";
}
}

return (::SetPriorityClass(Handle(), priority) != 0);
}

Expand Down
6 changes: 6 additions & 0 deletions content/browser/child_process_launcher_helper.h
Expand Up @@ -243,6 +243,12 @@ class ChildProcessLauncherHelper
std::unique_ptr<SandboxedProcessLauncherDelegate> delegate_;
base::WeakPtr<ChildProcessLauncher> child_process_launcher_;

#if BUILDFLAG(IS_WIN)
// Whether the child process is backgrounded, the state is stored to avoid
// setting the process priority repeatedly.
bool is_process_backgrounded_ = false;
#endif

// The PlatformChannel that will be used to transmit an invitation to the
// child process in most cases. Only used if the platform's helper
// implementation doesn't return a server endpoint from
Expand Down
7 changes: 5 additions & 2 deletions content/browser/child_process_launcher_helper_win.cc
Expand Up @@ -118,8 +118,11 @@ void ChildProcessLauncherHelper::SetProcessBackgroundedOnLauncherThread(
base::Process process,
bool is_background) {
DCHECK(CurrentlyOnProcessLauncherTaskRunner());
if (process.CanBackgroundProcesses())
process.SetProcessBackgrounded(is_background);
if (process.CanBackgroundProcesses() &&
is_process_backgrounded_ != is_background) {
is_process_backgrounded_ = is_background;
process.SetProcessBackgrounded(is_process_backgrounded_);
}
}

} // namespace internal
Expand Down

0 comments on commit 2808be7

Please sign in to comment.