Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define thread priority enum and set thread priority for all threads in Engine #30605

Merged
merged 2 commits into from
Feb 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions fml/concurrent_message_loop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ ConcurrentMessageLoop::ConcurrentMessageLoop(size_t worker_count)
: worker_count_(std::max<size_t>(worker_count, 1ul)) {
for (size_t i = 0; i < worker_count_; ++i) {
workers_.emplace_back([i, this]() {
fml::Thread::SetCurrentThreadName(
std::string{"io.worker." + std::to_string(i + 1)});
fml::Thread::SetCurrentThreadName(fml::Thread::ThreadConfig(
std::string{"io.worker." + std::to_string(i + 1)}));
WorkerMain();
});
}
Expand Down
77 changes: 44 additions & 33 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,38 +24,6 @@

namespace fml {

Thread::Thread(const std::string& name) : joined_(false) {
fml::AutoResetWaitableEvent latch;
fml::RefPtr<fml::TaskRunner> runner;
thread_ = std::make_unique<std::thread>([&latch, &runner, name]() -> void {
SetCurrentThreadName(name);
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = MessageLoop::GetCurrent();
runner = loop.GetTaskRunner();
latch.Signal();
loop.Run();
});
latch.Wait();
task_runner_ = runner;
}

Thread::~Thread() {
Join();
}

fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
return task_runner_;
}

void Thread::Join() {
if (joined_) {
return;
}
joined_ = true;
task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
thread_->join();
}

#if defined(FML_OS_WIN)
// The information on how to set the thread name comes from
// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
Expand All @@ -67,7 +36,7 @@ typedef struct tagTHREADNAME_INFO {
} THREADNAME_INFO;
#endif

void Thread::SetCurrentThreadName(const std::string& name) {
void SetThreadName(const std::string& name) {
if (name == "") {
return;
}
Expand All @@ -94,4 +63,46 @@ void Thread::SetCurrentThreadName(const std::string& name) {
#endif
}

void Thread::SetCurrentThreadName(const Thread::ThreadConfig& config) {
SetThreadName(config.name);
}

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

Thread::Thread(const ThreadConfigSetter& setter, const ThreadConfig& config)
: joined_(false) {
fml::AutoResetWaitableEvent latch;
fml::RefPtr<fml::TaskRunner> runner;

thread_ = std::make_unique<std::thread>(
[&latch, &runner, setter, config]() -> void {
setter(config);
fml::MessageLoop::EnsureInitializedForCurrentThread();
auto& loop = MessageLoop::GetCurrent();
runner = loop.GetTaskRunner();
latch.Signal();
loop.Run();
});
latch.Wait();
task_runner_ = runner;
}

Thread::~Thread() {
Join();
}

fml::RefPtr<fml::TaskRunner> Thread::GetTaskRunner() const {
return task_runner_;
}

void Thread::Join() {
if (joined_) {
return;
}
joined_ = true;
task_runner_->PostTask([]() { MessageLoop::GetCurrent().Terminate(); });
thread_->join();
}

} // namespace fml
37 changes: 36 additions & 1 deletion fml/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#define FLUTTER_FML_THREAD_H_

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

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

class Thread {
public:
/// 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 the thread info include thread name, thread priority.
struct ThreadConfig {
ThreadConfig(const std::string& name, ThreadPriority priority)
: name(name), priority(priority) {}

explicit ThreadConfig(const std::string& name)
: ThreadConfig(name, ThreadPriority::NORMAL) {}

ThreadConfig() : ThreadConfig("", ThreadPriority::NORMAL) {}

std::string name;
ThreadPriority priority;
};

using ThreadConfigSetter = std::function<void(const ThreadConfig&)>;

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

explicit Thread(const ThreadConfigSetter& setter,
const ThreadConfig& config = ThreadConfig());

~Thread();

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

void Join();

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

private:
std::unique_ptr<std::thread> thread_;

fml::RefPtr<fml::TaskRunner> task_runner_;

std::atomic_bool joined_;

FML_DISALLOW_COPY_AND_ASSIGN(Thread);
Expand Down
86 changes: 86 additions & 0 deletions fml/thread_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,18 @@

#include "flutter/fml/thread.h"

#if defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_ANDROID)
#define FLUTTER_PTHREAD_SUPPORTED 1
#else
#define FLUTTER_PTHREAD_SUPPORTED 0
#endif

#if FLUTTER_PTHREAD_SUPPORTED
#include <pthread.h>
#else
#endif
gaaclarke marked this conversation as resolved.
Show resolved Hide resolved

#include <memory>
#include "gtest/gtest.h"

TEST(Thread, CanStartAndEnd) {
Expand All @@ -24,3 +36,77 @@ TEST(Thread, HasARunningMessageLoop) {
thread.Join();
ASSERT_TRUE(done);
}

#if FLUTTER_PTHREAD_SUPPORTED
TEST(Thread, ThreadNameCreatedWithConfig) {
const std::string name = "Thread1";
fml::Thread thread(name);

bool done = false;
thread.GetTaskRunner()->PostTask([&done, &name]() {
done = true;
char thread_name[8];
pthread_t current_thread = pthread_self();
pthread_getname_np(current_thread, thread_name, 8);
ASSERT_EQ(thread_name, name);
});
thread.Join();
ASSERT_TRUE(done);
}

static void MockThreadConfigSetter(const fml::Thread::ThreadConfig& config) {
// set thread name
fml::Thread::SetCurrentThreadName(config);

pthread_t tid = pthread_self();
struct sched_param param;
int policy = SCHED_OTHER;
switch (config.priority) {
case fml::Thread::ThreadPriority::DISPLAY:
param.sched_priority = 10;
break;
default:
param.sched_priority = 1;
}
pthread_setschedparam(tid, policy, &param);
}

TEST(Thread, ThreadPriorityCreatedWithConfig) {
const std::string thread1_name = "Thread1";
const std::string thread2_name = "Thread2";

fml::Thread thread(MockThreadConfigSetter,
fml::Thread::ThreadConfig(
thread1_name, fml::Thread::ThreadPriority::NORMAL));
bool done = false;

struct sched_param param;
int policy;
thread.GetTaskRunner()->PostTask([&]() {
done = true;
char thread_name[8];
pthread_t current_thread = pthread_self();
pthread_getname_np(current_thread, thread_name, 8);
pthread_getschedparam(current_thread, &policy, &param);
ASSERT_EQ(thread_name, thread1_name);
ASSERT_EQ(policy, SCHED_OTHER);
ASSERT_EQ(param.sched_priority, 1);
});

fml::Thread thread2(MockThreadConfigSetter,
fml::Thread::ThreadConfig(
thread2_name, fml::Thread::ThreadPriority::DISPLAY));
thread2.GetTaskRunner()->PostTask([&]() {
done = true;
char thread_name[8];
pthread_t current_thread = pthread_self();
pthread_getname_np(current_thread, thread_name, 8);
pthread_getschedparam(current_thread, &policy, &param);
ASSERT_EQ(thread_name, thread2_name);
ASSERT_EQ(policy, SCHED_OTHER);
ASSERT_EQ(param.sched_priority, 10);
});
thread.Join();
ASSERT_TRUE(done);
}
#endif
12 changes: 6 additions & 6 deletions lib/ui/ui_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ class Fixture : public testing::FixtureTest {
};

static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) {
ThreadHost thread_host("test",
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI);
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
"test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI));
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(),
Expand Down Expand Up @@ -68,9 +68,9 @@ static void BM_PlatformMessageResponseDartComplete(benchmark::State& state) {
}

static void BM_PathVolatilityTracker(benchmark::State& state) {
ThreadHost thread_host("test",
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI);
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
"test", ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI));
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(),
Expand Down
4 changes: 2 additions & 2 deletions shell/common/shell_benchmarks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ static void StartupAndShutdownShell(benchmark::State& state,
};
}

thread_host = std::make_unique<ThreadHost>(
thread_host = std::make_unique<ThreadHost>(ThreadHost::ThreadHostConfig(
"io.flutter.bench.", ThreadHost::Type::Platform |
ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI);
ThreadHost::Type::IO | ThreadHost::Type::UI));

TaskRunners task_runners("test",
thread_host->platform_thread->GetTaskRunner(),
Expand Down
17 changes: 10 additions & 7 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -264,9 +264,10 @@ TEST_F(ShellTest, InitializeWithInvalidThreads) {
TEST_F(ShellTest, InitializeWithDifferentThreads) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
Settings settings = CreateSettingsForFixture();
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI);
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
"io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI));
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(),
Expand Down Expand Up @@ -3112,8 +3113,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeAppends) {
TEST_F(ShellTest, UpdateAssetResolverByTypeNull) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
Settings settings = CreateSettingsForFixture();
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform);
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
"io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform));
auto task_runner = thread_host.platform_thread->GetTaskRunner();
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
task_runner);
Expand Down Expand Up @@ -3149,8 +3151,9 @@ TEST_F(ShellTest, UpdateAssetResolverByTypeNull) {
TEST_F(ShellTest, UpdateAssetResolverByTypeDoesNotReplaceMismatchType) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning());
Settings settings = CreateSettingsForFixture();
ThreadHost thread_host("io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform);
ThreadHost thread_host(ThreadHost::ThreadHostConfig(
"io.flutter.test." + GetCurrentTestName() + ".",
ThreadHost::Type::Platform));
auto task_runner = thread_host.platform_thread->GetTaskRunner();
TaskRunners task_runners("test", task_runner, task_runner, task_runner,
task_runner);
Expand Down
Loading