Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 2963aaf

Browse files
committed
Define thread priority enum and set thread priority for all threads in engine
1 parent e7ff250 commit 2963aaf

File tree

6 files changed

+232
-44
lines changed

6 files changed

+232
-44
lines changed

fml/thread.cc

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include <memory>
1010
#include <string>
11+
#include <utility>
1112

1213
#include "flutter/fml/build_config.h"
1314
#include "flutter/fml/message_loop.h"
@@ -23,11 +24,24 @@
2324

2425
namespace fml {
2526

26-
Thread::Thread(const std::string& name) : joined_(false) {
27+
Thread::ThreadConfig::ThreadConfig(const std::string& name,
28+
ThreadPriority priority)
29+
: thread_name_(name), thread_priority_(priority) {}
30+
31+
void Thread::ThreadConfig::SetCurrentThreadName() {
32+
Thread::SetCurrentThreadName(thread_name_);
33+
}
34+
35+
Thread::Thread(const std::string& name)
36+
: Thread(ThreadConfig::DefaultConfigure(name)) {}
37+
38+
Thread::Thread(std::unique_ptr<Thread::ThreadConfig> configurer)
39+
: thread_configurer_(std::move(configurer)), joined_(false) {
2740
fml::AutoResetWaitableEvent latch;
2841
fml::RefPtr<fml::TaskRunner> runner;
29-
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
30-
SetCurrentThreadName(name);
42+
thread_ = std::make_unique<std::thread>([&]() -> void {
43+
thread_configurer_->SetCurrentThreadName();
44+
thread_configurer_->SetCurrentThreadPriority();
3145
fml::MessageLoop::EnsureInitializedForCurrentThread();
3246
auto& loop = MessageLoop::GetCurrent();
3347
runner = loop.GetTaskRunner();

fml/thread.h

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <atomic>
99
#include <memory>
10+
#include <string>
1011
#include <thread>
1112

1213
#include "flutter/fml/macros.h"
@@ -16,18 +17,58 @@ namespace fml {
1617

1718
class Thread {
1819
public:
19-
explicit Thread(const std::string& name = "");
20+
// Valid values for priority of Thread
21+
enum class ThreadPriority : int {
22+
// Suitable for threads that shouldn't disrupt high priority work.
23+
BACKGROUND,
24+
// Default priority level.
25+
NORMAL,
26+
// Suitable for threads which generate data for the display.
27+
DISPLAY,
28+
// Suitable for thread which raster data
29+
RASTER,
30+
};
31+
32+
/// The ThreadConfig is used for setting thread perorities
33+
class ThreadConfig {
34+
public:
35+
explicit ThreadConfig(const std::string& name = "",
36+
ThreadPriority priority = ThreadPriority::NORMAL);
37+
38+
static std::unique_ptr<ThreadConfig> DefaultConfigure(
39+
const std::string& name = "") {
40+
return std::make_unique<ThreadConfig>(name);
41+
}
42+
43+
ThreadPriority thread_priority() const { return thread_priority_; }
44+
45+
const std::string& thread_name() const { return thread_name_; }
46+
virtual void SetCurrentThreadName();
47+
virtual void SetCurrentThreadPriority() {}
48+
virtual ~ThreadConfig() = default;
49+
50+
private:
51+
const std::string thread_name_;
52+
ThreadPriority thread_priority_;
53+
};
54+
55+
explicit Thread(const std::string& name);
56+
57+
explicit Thread(std::unique_ptr<ThreadConfig> configurer =
58+
ThreadConfig::DefaultConfigure());
2059

2160
~Thread();
2261

2362
fml::RefPtr<fml::TaskRunner> GetTaskRunner() const;
2463

25-
void Join();
26-
2764
static void SetCurrentThreadName(const std::string& name);
2865

66+
void Join();
67+
2968
private:
3069
std::unique_ptr<std::thread> thread_;
70+
/// ThreadConfigure is used for setting thread configure some like `priority`
71+
std::unique_ptr<ThreadConfig> thread_configurer_;
3172
fml::RefPtr<fml::TaskRunner> task_runner_;
3273
std::atomic_bool joined_;
3374

shell/common/thread_host.cc

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,73 @@
44

55
#include "flutter/shell/common/thread_host.h"
66

7+
#include <algorithm>
8+
#include <memory>
9+
#include <string>
10+
#include <utility>
11+
712
namespace flutter {
813

14+
std::string ThreadHost::ThreadName(Type type, const std::string& prefix) {
15+
switch (type) {
16+
case Type::Platform:
17+
return prefix + ".platform";
18+
case Type::UI:
19+
return prefix + ".ui";
20+
case Type::IO:
21+
return prefix + ".io";
22+
case Type::RASTER:
23+
return prefix + ".raster";
24+
case Type::Profiler:
25+
return prefix + ".profiler";
26+
}
27+
}
28+
29+
std::unique_ptr<fml::Thread> ThreadHost::CreateThread(
30+
Type type,
31+
ThreadHost::ThreadConfig configure) {
32+
std::string name = ThreadName(type, name_prefix);
33+
if (configure != nullptr) {
34+
return std::make_unique<fml::Thread>(std::move(configure));
35+
}
36+
return std::make_unique<fml::Thread>(
37+
fml::Thread::ThreadConfig::DefaultConfigure(name));
38+
}
39+
940
ThreadHost::ThreadHost() = default;
1041

1142
ThreadHost::ThreadHost(ThreadHost&&) = default;
1243

13-
ThreadHost::ThreadHost(std::string name_prefix_arg, uint64_t mask)
44+
ThreadHost::ThreadHost(std::string name_prefix_arg,
45+
uint64_t mask,
46+
ThreadHostConfig configure_host)
1447
: name_prefix(name_prefix_arg) {
1548
if (mask & ThreadHost::Type::Platform) {
16-
platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
49+
platform_thread =
50+
CreateThread(ThreadHost::Type::Platform,
51+
std::move(configure_host.platform_configure));
1752
}
1853

1954
if (mask & ThreadHost::Type::UI) {
20-
ui_thread = std::make_unique<fml::Thread>(name_prefix + ".ui");
55+
ui_thread = CreateThread(ThreadHost::Type::UI,
56+
std::move(configure_host.ui_configure));
2157
}
2258

2359
if (mask & ThreadHost::Type::RASTER) {
24-
raster_thread = std::make_unique<fml::Thread>(name_prefix + ".raster");
60+
raster_thread = CreateThread(ThreadHost::Type::RASTER,
61+
std::move(configure_host.raster_configure));
2562
}
2663

2764
if (mask & ThreadHost::Type::IO) {
28-
io_thread = std::make_unique<fml::Thread>(name_prefix + ".io");
65+
io_thread = CreateThread(ThreadHost::Type::IO,
66+
std::move(configure_host.io_configure));
2967
}
3068

3169
if (mask & ThreadHost::Type::Profiler) {
32-
profiler_thread = std::make_unique<fml::Thread>(name_prefix + ".profiler");
70+
profiler_thread =
71+
CreateThread(ThreadHost::Type::Profiler,
72+
std::move(configure_host.profiler_configure));
73+
;
3374
}
3475
}
3576

shell/common/thread_host.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#define FLUTTER_SHELL_COMMON_THREAD_HOST_H_
77

88
#include <memory>
9+
#include <string>
910

1011
#include "flutter/fml/macros.h"
1112
#include "flutter/fml/thread.h"
@@ -22,6 +23,19 @@ struct ThreadHost {
2223
Profiler = 1 << 4,
2324
};
2425

26+
static std::string ThreadName(Type type, const std::string& prefix = "");
27+
28+
using ThreadConfig = std::unique_ptr<fml::Thread::ThreadConfig>;
29+
/// The collection of all the thread configures, and we create custom thread
30+
/// configure in engine to info the thread.
31+
struct ThreadHostConfig {
32+
ThreadConfig platform_configure;
33+
ThreadConfig ui_configure;
34+
ThreadConfig raster_configure;
35+
ThreadConfig io_configure;
36+
ThreadConfig profiler_configure;
37+
};
38+
2539
std::string name_prefix;
2640
std::unique_ptr<fml::Thread> platform_thread;
2741
std::unique_ptr<fml::Thread> ui_thread;
@@ -35,9 +49,14 @@ struct ThreadHost {
3549

3650
ThreadHost& operator=(ThreadHost&&) = default;
3751

38-
ThreadHost(std::string name_prefix, uint64_t type_mask);
52+
ThreadHost(std::string name_prefix,
53+
uint64_t type_mask,
54+
ThreadHostConfig configure_host = ThreadHostConfig());
3955

4056
~ThreadHost();
57+
58+
private:
59+
std::unique_ptr<fml::Thread> CreateThread(Type type, ThreadConfig configure);
4160
};
4261

4362
} // namespace flutter

shell/platform/android/android_shell_holder.cc

Lines changed: 56 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,45 @@
3232

3333
namespace flutter {
3434

35+
/// Inheriting ThreadConfigurer and use Android platform thread API to configure
36+
/// the thread priorities
37+
class PlatformAndroidThreadConfig : public fml::Thread::ThreadConfig {
38+
public:
39+
using fml::Thread::ThreadConfig::ThreadConfig;
40+
41+
void SetCurrentThreadPriority() override {
42+
switch (thread_priority()) {
43+
case fml::Thread::ThreadPriority::BACKGROUND:
44+
if (::setpriority(PRIO_PROCESS, 0, 10) != 0) {
45+
FML_LOG(ERROR) << "Failed to set IO task runner priority";
46+
}
47+
break;
48+
case fml::Thread::ThreadPriority::DISPLAY: {
49+
if (::setpriority(PRIO_PROCESS, 0, -1) != 0) {
50+
FML_LOG(ERROR) << "Failed to set UI task runner priority";
51+
}
52+
break;
53+
}
54+
case fml::Thread::ThreadPriority::RASTER: {
55+
// Android describes -8 as "most important display threads, for
56+
// compositing the screen and retrieving input events". Conservatively
57+
// set the raster thread to slightly lower priority than it.
58+
if (::setpriority(PRIO_PROCESS, 0, -5) != 0) {
59+
// Defensive fallback. Depending on the OEM, it may not be possible
60+
// to set priority to -5.
61+
if (::setpriority(PRIO_PROCESS, 0, -2) != 0) {
62+
FML_LOG(ERROR) << "Failed to set raster task runner priority";
63+
}
64+
}
65+
}
66+
default:
67+
if (::setpriority(PRIO_PROCESS, 0, 0) != 0) {
68+
FML_LOG(ERROR) << "Failed to set priority";
69+
}
70+
}
71+
}
72+
};
73+
3574
static PlatformData GetDefaultPlatformData() {
3675
PlatformData platform_data;
3776
platform_data.lifecycle_state = "AppLifecycleState.detached";
@@ -45,10 +84,23 @@ AndroidShellHolder::AndroidShellHolder(
4584
static size_t thread_host_count = 1;
4685
auto thread_label = std::to_string(thread_host_count++);
4786

48-
thread_host_ = std::make_shared<ThreadHost>();
49-
*thread_host_ = {thread_label, ThreadHost::Type::UI |
50-
ThreadHost::Type::RASTER |
51-
ThreadHost::Type::IO};
87+
auto ui_thread_name = flutter::ThreadHost::ThreadName(
88+
flutter::ThreadHost::Type::UI, thread_label);
89+
auto raster_thread_name = flutter::ThreadHost::ThreadName(
90+
flutter::ThreadHost::Type::UI, thread_label);
91+
auto io_thread_name = flutter::ThreadHost::ThreadName(
92+
flutter::ThreadHost::Type::UI, thread_label);
93+
94+
thread_host_ = std::make_shared<ThreadHost>(
95+
thread_label,
96+
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO,
97+
(flutter::ThreadHost::ThreadHostConfig){
98+
.ui_configure = std::make_unique<PlatformAndroidThreadConfig>(
99+
ui_thread_name, fml::Thread::ThreadPriority::DISPLAY),
100+
.raster_configure = std::make_unique<PlatformAndroidThreadConfig>(
101+
raster_thread_name, fml::Thread::ThreadPriority::RASTER),
102+
.io_configure = std::make_unique<PlatformAndroidThreadConfig>(
103+
io_thread_name, fml::Thread::ThreadPriority::BACKGROUND)});
52104

53105
fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
54106
Shell::CreateCallback<PlatformView> on_create_platform_view =
@@ -91,28 +143,6 @@ AndroidShellHolder::AndroidShellHolder(
91143
ui_runner, // ui
92144
io_runner // io
93145
);
94-
task_runners.GetRasterTaskRunner()->PostTask([]() {
95-
// Android describes -8 as "most important display threads, for
96-
// compositing the screen and retrieving input events". Conservatively
97-
// set the raster thread to slightly lower priority than it.
98-
if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
99-
// Defensive fallback. Depending on the OEM, it may not be possible
100-
// to set priority to -5.
101-
if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
102-
FML_LOG(ERROR) << "Failed to set raster task runner priority";
103-
}
104-
}
105-
});
106-
task_runners.GetUITaskRunner()->PostTask([]() {
107-
if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
108-
FML_LOG(ERROR) << "Failed to set UI task runner priority";
109-
}
110-
});
111-
task_runners.GetIOTaskRunner()->PostTask([]() {
112-
if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
113-
FML_LOG(ERROR) << "Failed to set IO task runner priority";
114-
}
115-
});
116146

117147
shell_ =
118148
Shell::Create(GetDefaultPlatformData(), // window data

0 commit comments

Comments
 (0)