未验证 提交 a1840379 编写于 作者: L liyuqian 提交者: GitHub

Send timings of the first frame without batching (#9424)

For https://github.com/flutter/flutter/issues/34867

Test added:
* ReportTimingsIsCalledImmediatelyAfterTheFirstFrame
上级 215096cc
...@@ -19,7 +19,8 @@ typedef FrameCallback = void Function(Duration duration); ...@@ -19,7 +19,8 @@ typedef FrameCallback = void Function(Duration duration);
/// overhead (as this is available in the release mode). The list is sorted in /// overhead (as this is available in the release mode). The list is sorted in
/// ascending order of time (earliest frame first). The timing of any frame /// ascending order of time (earliest frame first). The timing of any frame
/// will be sent within about 1 second (100ms if in the profile/debug mode) /// will be sent within about 1 second (100ms if in the profile/debug mode)
/// even if there are no later frames to batch. /// even if there are no later frames to batch. The timing of the first frame
/// will be sent immediately without batching.
/// {@endtemplate} /// {@endtemplate}
typedef TimingsCallback = void Function(List<FrameTiming> timings); typedef TimingsCallback = void Function(List<FrameTiming> timings);
......
...@@ -938,7 +938,8 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) { ...@@ -938,7 +938,8 @@ void Shell::OnFrameRasterized(const FrameTiming& timing) {
// require a latency of no more than 100ms. Hence we lower that 1-second // require a latency of no more than 100ms. Hence we lower that 1-second
// threshold to 100ms because performance overhead isn't that critical in // threshold to 100ms because performance overhead isn't that critical in
// those cases. // those cases.
if (UnreportedFramesCount() >= 100) { if (!first_frame_rasterized_ || UnreportedFramesCount() >= 100) {
first_frame_rasterized_ = true;
ReportTimings(); ReportTimings();
} else if (!frame_timings_report_scheduled_) { } else if (!frame_timings_report_scheduled_) {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
......
...@@ -110,6 +110,8 @@ class Shell final : public PlatformView::Delegate, ...@@ -110,6 +110,8 @@ class Shell final : public PlatformView::Delegate,
bool is_setup_ = false; bool is_setup_ = false;
uint64_t next_pointer_flow_id_ = 0; uint64_t next_pointer_flow_id_ = 0;
bool first_frame_rasterized_ = false;
// Written in the UI thread and read from the GPU thread. Hence make it // Written in the UI thread and read from the GPU thread. Hence make it
// atomic. // atomic.
std::atomic<bool> needs_report_timings_{false}; std::atomic<bool> needs_report_timings_{false};
......
...@@ -156,7 +156,7 @@ TEST_F(ShellTest, InitializeWithGPUAndPlatformThreadsTheSame) { ...@@ -156,7 +156,7 @@ TEST_F(ShellTest, InitializeWithGPUAndPlatformThreadsTheSame) {
TEST_F(ShellTest, FixturesAreFunctional) { TEST_F(ShellTest, FixturesAreFunctional) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning()); ASSERT_FALSE(DartVMRef::IsInstanceRunning());
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
auto shell = CreateShell(std::move(settings)); auto shell = CreateShell(settings);
ASSERT_TRUE(ValidateShell(shell.get())); ASSERT_TRUE(ValidateShell(shell.get()));
auto configuration = RunConfiguration::InferFromSettings(settings); auto configuration = RunConfiguration::InferFromSettings(settings);
...@@ -178,7 +178,7 @@ TEST_F(ShellTest, FixturesAreFunctional) { ...@@ -178,7 +178,7 @@ TEST_F(ShellTest, FixturesAreFunctional) {
TEST_F(ShellTest, SecondaryIsolateBindingsAreSetupViaShellSettings) { TEST_F(ShellTest, SecondaryIsolateBindingsAreSetupViaShellSettings) {
ASSERT_FALSE(DartVMRef::IsInstanceRunning()); ASSERT_FALSE(DartVMRef::IsInstanceRunning());
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
auto shell = CreateShell(std::move(settings)); auto shell = CreateShell(settings);
ASSERT_TRUE(ValidateShell(shell.get())); ASSERT_TRUE(ValidateShell(shell.get()));
auto configuration = RunConfiguration::InferFromSettings(settings); auto configuration = RunConfiguration::InferFromSettings(settings);
...@@ -251,7 +251,7 @@ TEST_F(ShellTest, WhitelistedDartVMFlag) { ...@@ -251,7 +251,7 @@ TEST_F(ShellTest, WhitelistedDartVMFlag) {
TEST_F(ShellTest, NoNeedToReportTimingsByDefault) { TEST_F(ShellTest, NoNeedToReportTimingsByDefault) {
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(std::move(settings)); std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer // Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get()); PlatformViewNotifyCreated(shell.get());
...@@ -278,7 +278,7 @@ TEST_F(ShellTest, NoNeedToReportTimingsByDefault) { ...@@ -278,7 +278,7 @@ TEST_F(ShellTest, NoNeedToReportTimingsByDefault) {
TEST_F(ShellTest, NeedsReportTimingsIsSetWithCallback) { TEST_F(ShellTest, NeedsReportTimingsIsSetWithCallback) {
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(std::move(settings)); std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer // Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get()); PlatformViewNotifyCreated(shell.get());
...@@ -315,7 +315,7 @@ static void CheckFrameTimings(const std::vector<FrameTiming>& timings, ...@@ -315,7 +315,7 @@ static void CheckFrameTimings(const std::vector<FrameTiming>& timings,
TEST_F(ShellTest, ReportTimingsIsCalled) { TEST_F(ShellTest, ReportTimingsIsCalled) {
fml::TimePoint start = fml::TimePoint::Now(); fml::TimePoint start = fml::TimePoint::Now();
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(std::move(settings)); std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer // Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get()); PlatformViewNotifyCreated(shell.get());
...@@ -381,7 +381,7 @@ TEST_F(ShellTest, FrameRasterizedCallbackIsCalled) { ...@@ -381,7 +381,7 @@ TEST_F(ShellTest, FrameRasterizedCallbackIsCalled) {
timingLatch.Signal(); timingLatch.Signal();
}; };
std::unique_ptr<Shell> shell = CreateShell(std::move(settings)); std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer // Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get()); PlatformViewNotifyCreated(shell.get());
...@@ -433,13 +433,13 @@ TEST(SettingsTest, FrameTimingSetsAndGetsProperly) { ...@@ -433,13 +433,13 @@ TEST(SettingsTest, FrameTimingSetsAndGetsProperly) {
} }
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE #if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_RELEASE
TEST_F(ShellTest, ReportTimingsIsCalledSoonerInNonReleaseMode) {
#else
TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) { TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) {
#else
TEST_F(ShellTest, ReportTimingsIsCalledSoonerInNonReleaseMode) {
#endif #endif
fml::TimePoint start = fml::TimePoint::Now(); fml::TimePoint start = fml::TimePoint::Now();
auto settings = CreateSettingsForFixture(); auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(std::move(settings)); std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer // Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get()); PlatformViewNotifyCreated(shell.get());
...@@ -447,19 +447,23 @@ TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) { ...@@ -447,19 +447,23 @@ TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) {
auto configuration = RunConfiguration::InferFromSettings(settings); auto configuration = RunConfiguration::InferFromSettings(settings);
ASSERT_TRUE(configuration.IsValid()); ASSERT_TRUE(configuration.IsValid());
configuration.SetEntrypoint("reportTimingsMain"); configuration.SetEntrypoint("reportTimingsMain");
fml::AutoResetWaitableEvent reportLatch;
// Wait for 2 reports: the first one is the immediate callback of the first
// frame; the second one will exercise the batching logic.
fml::CountDownLatch reportLatch(2);
std::vector<int64_t> timestamps; std::vector<int64_t> timestamps;
auto nativeTimingCallback = [&reportLatch, auto nativeTimingCallback = [&reportLatch,
&timestamps](Dart_NativeArguments args) { &timestamps](Dart_NativeArguments args) {
Dart_Handle exception = nullptr; Dart_Handle exception = nullptr;
timestamps = tonic::DartConverter<std::vector<int64_t>>::FromArguments( timestamps = tonic::DartConverter<std::vector<int64_t>>::FromArguments(
args, 0, exception); args, 0, exception);
reportLatch.Signal(); reportLatch.CountDown();
}; };
AddNativeCallback("NativeReportTimingsCallback", AddNativeCallback("NativeReportTimingsCallback",
CREATE_NATIVE_ENTRY(nativeTimingCallback)); CREATE_NATIVE_ENTRY(nativeTimingCallback));
RunEngine(shell.get(), std::move(configuration)); RunEngine(shell.get(), std::move(configuration));
PumpOneFrame(shell.get());
PumpOneFrame(shell.get()); PumpOneFrame(shell.get());
reportLatch.Wait(); reportLatch.Wait();
...@@ -479,5 +483,40 @@ TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) { ...@@ -479,5 +483,40 @@ TEST_F(ShellTest, ReportTimingsIsCalledLaterInReleaseMode) {
#endif #endif
} }
TEST_F(ShellTest, ReportTimingsIsCalledImmediatelyAfterTheFirstFrame) {
auto settings = CreateSettingsForFixture();
std::unique_ptr<Shell> shell = CreateShell(settings);
// Create the surface needed by rasterizer
PlatformViewNotifyCreated(shell.get());
auto configuration = RunConfiguration::InferFromSettings(settings);
ASSERT_TRUE(configuration.IsValid());
configuration.SetEntrypoint("reportTimingsMain");
fml::AutoResetWaitableEvent reportLatch;
std::vector<int64_t> timestamps;
auto nativeTimingCallback = [&reportLatch,
&timestamps](Dart_NativeArguments args) {
Dart_Handle exception = nullptr;
timestamps = tonic::DartConverter<std::vector<int64_t>>::FromArguments(
args, 0, exception);
reportLatch.Signal();
};
AddNativeCallback("NativeReportTimingsCallback",
CREATE_NATIVE_ENTRY(nativeTimingCallback));
RunEngine(shell.get(), std::move(configuration));
for (int i = 0; i < 10; i += 1) {
PumpOneFrame(shell.get());
}
reportLatch.Wait();
shell.reset();
// Check for the immediate callback of the first frame that doesn't wait for
// the other 9 frames to be rasterized.
ASSERT_EQ(timestamps.size(), FrameTiming::kCount);
}
} // namespace testing } // namespace testing
} // namespace flutter } // namespace flutter
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册