Skip to content

Commit

Permalink
Define thread priority enum and set thread priority for all threads i…
Browse files Browse the repository at this point in the history
…n Engine
  • Loading branch information
JsouLiang committed Dec 31, 2021
1 parent e7ff250 commit e24ee60
Show file tree
Hide file tree
Showing 6 changed files with 236 additions and 44 deletions.
20 changes: 17 additions & 3 deletions fml/thread.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include <memory>
#include <string>
#include <utility>

#include "flutter/fml/build_config.h"
#include "flutter/fml/message_loop.h"
Expand All @@ -23,11 +24,24 @@

namespace fml {

Thread::Thread(const std::string& name) : joined_(false) {
Thread::ThreadConfig::ThreadConfig(const std::string& name,
ThreadPriority priority)
: thread_name_(name), thread_priority_(priority) {}

void Thread::ThreadConfig::SetCurrentThreadName() {
Thread::SetCurrentThreadName(thread_name_);
}

Thread::Thread(const std::string& name)
: Thread(ThreadConfig::DefaultConfigure(name)) {}

Thread::Thread(std::unique_ptr<Thread::ThreadConfig> configurer)
: thread_configurer_(std::move(configurer)), joined_(false) {
fml::AutoResetWaitableEvent latch;
fml::RefPtr<fml::TaskRunner> runner;
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
SetCurrentThreadName(name);
thread_ = std::make_unique<std::thread>([&]() -> void {
thread_configurer_->SetCurrentThreadName();
thread_configurer_->SetCurrentThreadPriority();
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = MessageLoop::GetCurrent();
runner = loop.GetTaskRunner();
Expand Down
47 changes: 44 additions & 3 deletions fml/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <atomic>
#include <memory>
#include <string>
#include <thread>

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

class Thread {
public:
explicit Thread(const std::string& name = "");
// Valid values for priority of Thread
enum class ThreadPriority : int {
// Suitable for threads that shouldn't disrupt high priority work.
BACKGROUND,
// Default priority level.
NORMAL,
// Suitable for threads which generate data for the display.
DISPLAY,
// Suitable for thread which raster data
RASTER,
};

/// The ThreadConfig is used for setting thread perorities
class ThreadConfig {
public:
explicit ThreadConfig(const std::string& name = "",
ThreadPriority priority = ThreadPriority::NORMAL);

static std::unique_ptr<ThreadConfig> DefaultConfigure(
const std::string& name = "") {
return std::make_unique<ThreadConfig>(name);
}

ThreadPriority thread_priority() const { return thread_priority_; }

const std::string& thread_name() const { return thread_name_; }
virtual void SetCurrentThreadName();
virtual void SetCurrentThreadPriority() {}
virtual ~ThreadConfig() = default;

private:
const std::string thread_name_;
ThreadPriority thread_priority_;
};

explicit Thread(const std::string& name);

explicit Thread(std::unique_ptr<ThreadConfig> configurer =
ThreadConfig::DefaultConfigure());

~Thread();

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

void Join();

static void SetCurrentThreadName(const std::string& name);

void Join();

private:
std::unique_ptr<std::thread> thread_;
/// ThreadConfigure is used for setting thread configure some like `priority`
std::unique_ptr<ThreadConfig> thread_configurer_;
fml::RefPtr<fml::TaskRunner> task_runner_;
std::atomic_bool joined_;

Expand Down
53 changes: 47 additions & 6 deletions shell/common/thread_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,73 @@

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

#include <algorithm>
#include <memory>
#include <string>
#include <utility>

namespace flutter {

std::string ThreadHost::ThreadName(Type type, const std::string& prefix) {
switch (type) {
case Type::Platform:
return prefix + ".platform";
case Type::UI:
return prefix + ".ui";
case Type::IO:
return prefix + ".io";
case Type::RASTER:
return prefix + ".raster";
case Type::Profiler:
return prefix + ".profiler";
}
}

std::unique_ptr<fml::Thread> ThreadHost::CreateThread(
Type type,
ThreadHost::ThreadConfig configure) {
std::string name = ThreadName(type, name_prefix);
if (configure != nullptr) {
return std::make_unique<fml::Thread>(std::move(configure));
}
return std::make_unique<fml::Thread>(
fml::Thread::ThreadConfig::DefaultConfigure(name));
}

ThreadHost::ThreadHost() = default;

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

ThreadHost::ThreadHost(std::string name_prefix_arg, uint64_t mask)
ThreadHost::ThreadHost(std::string name_prefix_arg,
uint64_t mask,
ThreadHostConfig configure_host)
: name_prefix(name_prefix_arg) {
if (mask & ThreadHost::Type::Platform) {
platform_thread = std::make_unique<fml::Thread>(name_prefix + ".platform");
platform_thread =
CreateThread(ThreadHost::Type::Platform,
std::move(configure_host.platform_configure));
}

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

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

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

if (mask & ThreadHost::Type::Profiler) {
profiler_thread = std::make_unique<fml::Thread>(name_prefix + ".profiler");
profiler_thread =
CreateThread(ThreadHost::Type::Profiler,
std::move(configure_host.profiler_configure));
;
}
}

Expand Down
21 changes: 20 additions & 1 deletion shell/common/thread_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#define FLUTTER_SHELL_COMMON_THREAD_HOST_H_

#include <memory>
#include <string>

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

static std::string ThreadName(Type type, const std::string& prefix = "");

using ThreadConfig = std::unique_ptr<fml::Thread::ThreadConfig>;
/// The collection of all the thread configures, and we create custom thread
/// configure in engine to info the thread.
struct ThreadHostConfig {
ThreadConfig platform_configure;
ThreadConfig ui_configure;
ThreadConfig raster_configure;
ThreadConfig io_configure;
ThreadConfig profiler_configure;
};

std::string name_prefix;
std::unique_ptr<fml::Thread> platform_thread;
std::unique_ptr<fml::Thread> ui_thread;
Expand All @@ -35,9 +49,14 @@ struct ThreadHost {

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

ThreadHost(std::string name_prefix, uint64_t type_mask);
ThreadHost(std::string name_prefix,
uint64_t type_mask,
ThreadHostConfig configure_host = ThreadHostConfig());

~ThreadHost();

private:
std::unique_ptr<fml::Thread> CreateThread(Type type, ThreadConfig configure);
};

} // namespace flutter
Expand Down
84 changes: 58 additions & 26 deletions shell/platform/android/android_shell_holder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,47 @@

namespace flutter {

/// Inheriting ThreadConfigurer and use Android platform thread API to configure
/// the thread priorities
class PlatformAndroidThreadConfig : public fml::Thread::ThreadConfig {
public:
using fml::Thread::ThreadConfig::ThreadConfig;

void SetCurrentThreadPriority() override {
switch (thread_priority()) {
case fml::Thread::ThreadPriority::BACKGROUND: {
if (::setpriority(PRIO_PROCESS, 0, 10) != 0) {
FML_LOG(ERROR) << "Failed to set IO task runner priority";
}
break;
}
case fml::Thread::ThreadPriority::DISPLAY: {
if (::setpriority(PRIO_PROCESS, 0, -1) != 0) {
FML_LOG(ERROR) << "Failed to set UI task runner priority";
}
break;
}
case fml::Thread::ThreadPriority::RASTER: {
// Android describes -8 as "most important display threads, for
// compositing the screen and retrieving input events". Conservatively
// set the raster thread to slightly lower priority than it.
if (::setpriority(PRIO_PROCESS, 0, -5) != 0) {
// Defensive fallback. Depending on the OEM, it may not be possible
// to set priority to -5.
if (::setpriority(PRIO_PROCESS, 0, -2) != 0) {
FML_LOG(ERROR) << "Failed to set raster task runner priority";
}
}
break;
}
default:
if (::setpriority(PRIO_PROCESS, 0, 0) != 0) {
FML_LOG(ERROR) << "Failed to set priority";
}
}
}
};

static PlatformData GetDefaultPlatformData() {
PlatformData platform_data;
platform_data.lifecycle_state = "AppLifecycleState.detached";
Expand All @@ -45,10 +86,23 @@ AndroidShellHolder::AndroidShellHolder(
static size_t thread_host_count = 1;
auto thread_label = std::to_string(thread_host_count++);

thread_host_ = std::make_shared<ThreadHost>();
*thread_host_ = {thread_label, ThreadHost::Type::UI |
ThreadHost::Type::RASTER |
ThreadHost::Type::IO};
auto ui_thread_name = flutter::ThreadHost::ThreadName(
flutter::ThreadHost::Type::UI, thread_label);
auto raster_thread_name = flutter::ThreadHost::ThreadName(
flutter::ThreadHost::Type::UI, thread_label);
auto io_thread_name = flutter::ThreadHost::ThreadName(
flutter::ThreadHost::Type::UI, thread_label);

thread_host_ = std::make_shared<ThreadHost>(
thread_label,
ThreadHost::Type::UI | ThreadHost::Type::RASTER | ThreadHost::Type::IO,
(flutter::ThreadHost::ThreadHostConfig){
.ui_configure = std::make_unique<PlatformAndroidThreadConfig>(
ui_thread_name, fml::Thread::ThreadPriority::DISPLAY),
.raster_configure = std::make_unique<PlatformAndroidThreadConfig>(
raster_thread_name, fml::Thread::ThreadPriority::RASTER),
.io_configure = std::make_unique<PlatformAndroidThreadConfig>(
io_thread_name, fml::Thread::ThreadPriority::BACKGROUND)});

fml::WeakPtr<PlatformViewAndroid> weak_platform_view;
Shell::CreateCallback<PlatformView> on_create_platform_view =
Expand Down Expand Up @@ -91,28 +145,6 @@ AndroidShellHolder::AndroidShellHolder(
ui_runner, // ui
io_runner // io
);
task_runners.GetRasterTaskRunner()->PostTask([]() {
// Android describes -8 as "most important display threads, for
// compositing the screen and retrieving input events". Conservatively
// set the raster thread to slightly lower priority than it.
if (::setpriority(PRIO_PROCESS, gettid(), -5) != 0) {
// Defensive fallback. Depending on the OEM, it may not be possible
// to set priority to -5.
if (::setpriority(PRIO_PROCESS, gettid(), -2) != 0) {
FML_LOG(ERROR) << "Failed to set raster task runner priority";
}
}
});
task_runners.GetUITaskRunner()->PostTask([]() {
if (::setpriority(PRIO_PROCESS, gettid(), -1) != 0) {
FML_LOG(ERROR) << "Failed to set UI task runner priority";
}
});
task_runners.GetIOTaskRunner()->PostTask([]() {
if (::setpriority(PRIO_PROCESS, gettid(), 1) != 0) {
FML_LOG(ERROR) << "Failed to set IO task runner priority";
}
});

shell_ =
Shell::Create(GetDefaultPlatformData(), // window data
Expand Down
Loading

0 comments on commit e24ee60

Please sign in to comment.