Add support for setting thread priority in embedder.h and update windows embedding to do so (flutter/engine#31778)

This commit is contained in:
Jonah Williams
2022-03-03 21:21:03 -08:00
committed by GitHub
parent b046d20d3d
commit 643b1cd598
5 changed files with 96 additions and 5 deletions

View File

@@ -16,6 +16,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/make_copyable.h"
#include "flutter/fml/native_library.h"
#include "flutter/fml/thread.h"
#include "third_party/dart/runtime/bin/elf_loader.h"
#include "third_party/dart/runtime/include/dart_native_api.h"
@@ -1450,10 +1451,33 @@ FlutterEngineResult FlutterEngineInitialize(size_t version,
}
}
#endif
auto custom_task_runners = SAFE_ACCESS(args, custom_task_runners, nullptr);
auto thread_config_callback = [&custom_task_runners](
const fml::Thread::ThreadConfig& config) {
fml::Thread::SetCurrentThreadName(config);
if (!custom_task_runners || !custom_task_runners->thread_priority_setter) {
return;
}
FlutterThreadPriority priority = FlutterThreadPriority::kNormal;
switch (config.priority) {
case fml::Thread::ThreadPriority::BACKGROUND:
priority = FlutterThreadPriority::kBackground;
break;
case fml::Thread::ThreadPriority::NORMAL:
priority = FlutterThreadPriority::kNormal;
break;
case fml::Thread::ThreadPriority::DISPLAY:
priority = FlutterThreadPriority::kDisplay;
break;
case fml::Thread::ThreadPriority::RASTER:
priority = FlutterThreadPriority::kRaster;
break;
}
custom_task_runners->thread_priority_setter(priority);
};
auto thread_host =
flutter::EmbedderThreadHost::CreateEmbedderOrEngineManagedThreadHost(
SAFE_ACCESS(args, custom_task_runners, nullptr));
custom_task_runners, thread_config_callback);
if (!thread_host || !thread_host->IsValid()) {
return LOG_EMBEDDER_ERROR(kInvalidArguments,

View File

@@ -226,6 +226,18 @@ typedef enum {
kFlutterTextDirectionLTR = 2,
} FlutterTextDirection;
/// Valid values for priority of Thread.
typedef enum {
/// Suitable for threads that shouldn't disrupt high priority work.
kBackground = 0,
/// Default priority level.
kNormal = 1,
/// Suitable for threads which generate data for the display.
kDisplay = 2,
/// Suitable for thread which raster data.
kRaster = 3,
} FlutterThreadPriority;
typedef struct _FlutterEngine* FLUTTER_API_SYMBOL(FlutterEngine);
typedef struct {
@@ -1061,6 +1073,9 @@ typedef struct {
/// and platform task runners. This makes the Flutter engine use the same
/// thread for both task runners.
const FlutterTaskRunnerDescription* render_task_runner;
/// Specify a callback that is used to set the thread priority for embedder
/// task runners.
void (*thread_priority_setter)(FlutterThreadPriority);
} FlutterCustomTaskRunners;
typedef struct {

View File

@@ -261,6 +261,8 @@ bool FlutterWindowsEngine::RunWithEntrypoint(const char* entrypoint) {
FlutterCustomTaskRunners custom_task_runners = {};
custom_task_runners.struct_size = sizeof(FlutterCustomTaskRunners);
custom_task_runners.platform_task_runner = &platform_task_runner;
custom_task_runners.thread_priority_setter =
&WindowsPlatformThreadPrioritySetter;
FlutterProjectArgs args = {};
args.struct_size = sizeof(FlutterProjectArgs);

View File

@@ -32,6 +32,32 @@ namespace flutter {
class FlutterWindowsView;
// Update the thread priority for the Windows engine.
static void WindowsPlatformThreadPrioritySetter(
FlutterThreadPriority priority) {
// TODO(99502): Add support for tracing to the windows embedding so we can
// mark thread priorities and success/failure.
switch (priority) {
case FlutterThreadPriority::kBackground: {
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
break;
}
case FlutterThreadPriority::kDisplay: {
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
break;
}
case FlutterThreadPriority::kRaster: {
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
break;
}
case FlutterThreadPriority::kNormal: {
// For normal or default priority we do not need to set the priority
// class.
break;
}
}
}
// Manages state associated with the underlying FlutterEngine that isn't
// related to its display.
//
@@ -163,9 +189,7 @@ class FlutterWindowsEngine {
void UpdateSemanticsEnabled(bool enabled);
// Returns true if the semantics tree is enabled.
bool semantics_enabled() const {
return semantics_enabled_;
}
bool semantics_enabled() const { return semantics_enabled_; }
// Returns the native accessibility node with the given id.
gfx::NativeViewAccessible GetNativeAccessibleFromId(AccessibilityNodeId id);

View File

@@ -66,9 +66,14 @@ TEST(FlutterWindowsEngine, RunDoesExpectedInitialization) {
EXPECT_EQ(strcmp(args->dart_entrypoint_argv[1], "arg2"), 0);
EXPECT_NE(args->platform_message_callback, nullptr);
EXPECT_NE(args->custom_task_runners, nullptr);
EXPECT_NE(args->custom_task_runners->thread_priority_setter, nullptr);
EXPECT_EQ(args->custom_dart_entrypoint, nullptr);
EXPECT_NE(args->vsync_callback, nullptr);
args->custom_task_runners->thread_priority_setter(
FlutterThreadPriority::kRaster);
EXPECT_EQ(GetThreadPriority(GetCurrentThread()),
THREAD_PRIORITY_ABOVE_NORMAL);
return kSuccess;
}));
@@ -318,6 +323,27 @@ TEST(FlutterWindowsEngine, DispatchSemanticsAction) {
EXPECT_TRUE(called);
}
TEST(FlutterWindowsEngine, SetsThreadPriority) {
WindowsPlatformThreadPrioritySetter(FlutterThreadPriority::kBackground);
EXPECT_EQ(GetThreadPriority(GetCurrentThread()),
THREAD_PRIORITY_BELOW_NORMAL);
WindowsPlatformThreadPrioritySetter(FlutterThreadPriority::kDisplay);
EXPECT_EQ(GetThreadPriority(GetCurrentThread()),
THREAD_PRIORITY_ABOVE_NORMAL);
WindowsPlatformThreadPrioritySetter(FlutterThreadPriority::kRaster);
EXPECT_EQ(GetThreadPriority(GetCurrentThread()),
THREAD_PRIORITY_ABOVE_NORMAL);
// FlutterThreadPriority::kNormal does not change thread priority, reset to 0
// here.
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
WindowsPlatformThreadPrioritySetter(FlutterThreadPriority::kNormal);
EXPECT_EQ(GetThreadPriority(GetCurrentThread()), THREAD_PRIORITY_NORMAL);
}
TEST(FlutterWindowsEngine, AddPluginRegistrarDestructionCallback) {
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
EngineModifier modifier(engine.get());