Constant high CPU usage in beta Windows app #324
This commit is contained in:
parent
77c2992de3
commit
df516b981d
|
|
@ -4,7 +4,6 @@ project(runner LANGUAGES CXX)
|
||||||
add_executable(${BINARY_NAME} WIN32
|
add_executable(${BINARY_NAME} WIN32
|
||||||
"flutter_window.cpp"
|
"flutter_window.cpp"
|
||||||
"main.cpp"
|
"main.cpp"
|
||||||
"run_loop.cpp"
|
|
||||||
"utils.cpp"
|
"utils.cpp"
|
||||||
"win32_window.cpp"
|
"win32_window.cpp"
|
||||||
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
"${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc"
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,8 @@
|
||||||
|
|
||||||
#include "flutter/generated_plugin_registrant.h"
|
#include "flutter/generated_plugin_registrant.h"
|
||||||
|
|
||||||
FlutterWindow::FlutterWindow(RunLoop* run_loop,
|
FlutterWindow::FlutterWindow(const flutter::DartProject& project)
|
||||||
const flutter::DartProject& project)
|
: project_(project) {}
|
||||||
: run_loop_(run_loop), project_(project) {}
|
|
||||||
|
|
||||||
FlutterWindow::~FlutterWindow() {}
|
FlutterWindow::~FlutterWindow() {}
|
||||||
|
|
||||||
|
|
@ -26,14 +25,12 @@ bool FlutterWindow::OnCreate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
RegisterPlugins(flutter_controller_->engine());
|
RegisterPlugins(flutter_controller_->engine());
|
||||||
run_loop_->RegisterFlutterInstance(flutter_controller_->engine());
|
|
||||||
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
SetChildContent(flutter_controller_->view()->GetNativeWindow());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlutterWindow::OnDestroy() {
|
void FlutterWindow::OnDestroy() {
|
||||||
if (flutter_controller_) {
|
if (flutter_controller_) {
|
||||||
run_loop_->UnregisterFlutterInstance(flutter_controller_->engine());
|
|
||||||
flutter_controller_ = nullptr;
|
flutter_controller_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,16 +6,13 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include "run_loop.h"
|
|
||||||
#include "win32_window.h"
|
#include "win32_window.h"
|
||||||
|
|
||||||
// A window that does nothing but host a Flutter view.
|
// A window that does nothing but host a Flutter view.
|
||||||
class FlutterWindow : public Win32Window {
|
class FlutterWindow : public Win32Window {
|
||||||
public:
|
public:
|
||||||
// Creates a new FlutterWindow driven by the |run_loop|, hosting a
|
// Creates a new FlutterWindow hosting a Flutter view running |project|.
|
||||||
// Flutter view running |project|.
|
explicit FlutterWindow(const flutter::DartProject& project);
|
||||||
explicit FlutterWindow(RunLoop* run_loop,
|
|
||||||
const flutter::DartProject& project);
|
|
||||||
virtual ~FlutterWindow();
|
virtual ~FlutterWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -26,9 +23,6 @@ class FlutterWindow : public Win32Window {
|
||||||
LPARAM const lparam) noexcept override;
|
LPARAM const lparam) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// The run loop driving events for this window.
|
|
||||||
RunLoop* run_loop_;
|
|
||||||
|
|
||||||
// The project to run.
|
// The project to run.
|
||||||
flutter::DartProject project_;
|
flutter::DartProject project_;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#include "flutter_window.h"
|
#include "flutter_window.h"
|
||||||
#include "run_loop.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
|
|
@ -18,8 +17,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
// plugins.
|
// plugins.
|
||||||
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
|
||||||
|
|
||||||
RunLoop run_loop;
|
|
||||||
|
|
||||||
flutter::DartProject project(L"data");
|
flutter::DartProject project(L"data");
|
||||||
|
|
||||||
std::vector<std::string> command_line_arguments =
|
std::vector<std::string> command_line_arguments =
|
||||||
|
|
@ -27,7 +24,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
|
|
||||||
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
project.set_dart_entrypoint_arguments(std::move(command_line_arguments));
|
||||||
|
|
||||||
FlutterWindow window(&run_loop, project);
|
FlutterWindow window(project);
|
||||||
Win32Window::Point origin(10, 10);
|
Win32Window::Point origin(10, 10);
|
||||||
Win32Window::Size size(1280, 720);
|
Win32Window::Size size(1280, 720);
|
||||||
if (!window.CreateAndShow(L"Invoice Ninja", origin, size)) {
|
if (!window.CreateAndShow(L"Invoice Ninja", origin, size)) {
|
||||||
|
|
@ -35,7 +32,11 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
||||||
}
|
}
|
||||||
window.SetQuitOnClose(true);
|
window.SetQuitOnClose(true);
|
||||||
|
|
||||||
run_loop.Run();
|
::MSG msg;
|
||||||
|
while (::GetMessage(&msg, nullptr, 0, 0)) {
|
||||||
|
::TranslateMessage(&msg);
|
||||||
|
::DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
::CoUninitialize();
|
::CoUninitialize();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
#include "run_loop.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
RunLoop::RunLoop() {}
|
|
||||||
|
|
||||||
RunLoop::~RunLoop() {}
|
|
||||||
|
|
||||||
void RunLoop::Run() {
|
|
||||||
bool keep_running = true;
|
|
||||||
TimePoint next_flutter_event_time = TimePoint::clock::now();
|
|
||||||
while (keep_running) {
|
|
||||||
std::chrono::nanoseconds wait_duration =
|
|
||||||
std::max(std::chrono::nanoseconds(0),
|
|
||||||
next_flutter_event_time - TimePoint::clock::now());
|
|
||||||
::MsgWaitForMultipleObjects(
|
|
||||||
0, nullptr, FALSE, static_cast<DWORD>(wait_duration.count() / 1000),
|
|
||||||
QS_ALLINPUT);
|
|
||||||
bool processed_events = false;
|
|
||||||
MSG message;
|
|
||||||
// All pending Windows messages must be processed; MsgWaitForMultipleObjects
|
|
||||||
// won't return again for items left in the queue after PeekMessage.
|
|
||||||
while (::PeekMessage(&message, nullptr, 0, 0, PM_REMOVE)) {
|
|
||||||
processed_events = true;
|
|
||||||
if (message.message == WM_QUIT) {
|
|
||||||
keep_running = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
::TranslateMessage(&message);
|
|
||||||
::DispatchMessage(&message);
|
|
||||||
// Allow Flutter to process messages each time a Windows message is
|
|
||||||
// processed, to prevent starvation.
|
|
||||||
next_flutter_event_time =
|
|
||||||
std::min(next_flutter_event_time, ProcessFlutterMessages());
|
|
||||||
}
|
|
||||||
// If the PeekMessage loop didn't run, process Flutter messages.
|
|
||||||
if (!processed_events) {
|
|
||||||
next_flutter_event_time =
|
|
||||||
std::min(next_flutter_event_time, ProcessFlutterMessages());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunLoop::RegisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance) {
|
|
||||||
flutter_instances_.insert(flutter_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RunLoop::UnregisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance) {
|
|
||||||
flutter_instances_.erase(flutter_instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
RunLoop::TimePoint RunLoop::ProcessFlutterMessages() {
|
|
||||||
TimePoint next_event_time = TimePoint::max();
|
|
||||||
for (auto instance : flutter_instances_) {
|
|
||||||
std::chrono::nanoseconds wait_duration = instance->ProcessMessages();
|
|
||||||
if (wait_duration != std::chrono::nanoseconds::max()) {
|
|
||||||
next_event_time =
|
|
||||||
std::min(next_event_time, TimePoint::clock::now() + wait_duration);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return next_event_time;
|
|
||||||
}
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
#ifndef RUNNER_RUN_LOOP_H_
|
|
||||||
#define RUNNER_RUN_LOOP_H_
|
|
||||||
|
|
||||||
#include <flutter/flutter_engine.h>
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
#include <set>
|
|
||||||
|
|
||||||
// A runloop that will service events for Flutter instances as well
|
|
||||||
// as native messages.
|
|
||||||
class RunLoop {
|
|
||||||
public:
|
|
||||||
RunLoop();
|
|
||||||
~RunLoop();
|
|
||||||
|
|
||||||
// Prevent copying
|
|
||||||
RunLoop(RunLoop const&) = delete;
|
|
||||||
RunLoop& operator=(RunLoop const&) = delete;
|
|
||||||
|
|
||||||
// Runs the run loop until the application quits.
|
|
||||||
void Run();
|
|
||||||
|
|
||||||
// Registers the given Flutter instance for event servicing.
|
|
||||||
void RegisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance);
|
|
||||||
|
|
||||||
// Unregisters the given Flutter instance from event servicing.
|
|
||||||
void UnregisterFlutterInstance(
|
|
||||||
flutter::FlutterEngine* flutter_instance);
|
|
||||||
|
|
||||||
private:
|
|
||||||
using TimePoint = std::chrono::steady_clock::time_point;
|
|
||||||
|
|
||||||
// Processes all currently pending messages for registered Flutter instances.
|
|
||||||
TimePoint ProcessFlutterMessages();
|
|
||||||
|
|
||||||
std::set<flutter::FlutterEngine*> flutter_instances_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // RUNNER_RUN_LOOP_H_
|
|
||||||
Loading…
Reference in New Issue