added trace events for scheduling responses to platform messages (#34230)
diff --git a/lib/ui/ui_benchmarks.cc b/lib/ui/ui_benchmarks.cc
index 4c8239b..ce1d4c6 100644
--- a/lib/ui/ui_benchmarks.cc
+++ b/lib/ui/ui_benchmarks.cc
@@ -48,7 +48,7 @@
auto message = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(isolate->get(), closure),
- thread_host.ui_thread->GetTaskRunner());
+ thread_host.ui_thread->GetTaskRunner(), "");
message->Complete(std::move(mapping));
diff --git a/lib/ui/window/platform_configuration.cc b/lib/ui/window/platform_configuration.cc
index 3914578..bee2f79 100644
--- a/lib/ui/window/platform_configuration.cc
+++ b/lib/ui/window/platform_configuration.cc
@@ -97,7 +97,7 @@
if (!Dart_IsNull(callback)) {
response = fml::MakeRefCounted<PlatformMessageResponseDart>(
tonic::DartPersistentValue(dart_state, callback),
- dart_state->GetTaskRunners().GetUITaskRunner());
+ dart_state->GetTaskRunners().GetUITaskRunner(), name);
}
if (Dart_IsNull(data_handle)) {
dart_state->platform_configuration()->client()->HandlePlatformMessage(
diff --git a/lib/ui/window/platform_message_response_dart.cc b/lib/ui/window/platform_message_response_dart.cc
index f53fc41..39d55f4 100644
--- a/lib/ui/window/platform_message_response_dart.cc
+++ b/lib/ui/window/platform_message_response_dart.cc
@@ -8,17 +8,52 @@
#include "flutter/common/task_runners.h"
#include "flutter/fml/make_copyable.h"
+#include "flutter/fml/trace_event.h"
#include "third_party/tonic/dart_state.h"
#include "third_party/tonic/logging/dart_invoke.h"
#include "third_party/tonic/typed_data/dart_byte_data.h"
+static std::atomic<uint64_t> platform_message_counter = 1;
+
namespace flutter {
+namespace {
+template <typename Callback, typename TaskRunner, typename Result>
+void PostCompletion(Callback&& callback,
+ const TaskRunner& ui_task_runner,
+ bool* is_complete,
+ const std::string& channel,
+ Result&& result) {
+ if (callback.is_empty()) {
+ return;
+ }
+ FML_DCHECK(!*is_complete);
+ *is_complete = true;
+ uint64_t platform_message_id = platform_message_counter.fetch_add(1);
+ TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleResult",
+ platform_message_id, "channel", channel.c_str());
+ ui_task_runner->PostTask(fml::MakeCopyable(
+ [callback = std::move(callback), platform_message_id,
+ result = std::move(result), channel = channel]() mutable {
+ TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleResult",
+ platform_message_id);
+ std::shared_ptr<tonic::DartState> dart_state =
+ callback.dart_state().lock();
+ if (!dart_state) {
+ return;
+ }
+ tonic::DartState::Scope scope(dart_state);
+ tonic::DartInvoke(callback.Release(), {result()});
+ }));
+}
+} // namespace
PlatformMessageResponseDart::PlatformMessageResponseDart(
tonic::DartPersistentValue callback,
- fml::RefPtr<fml::TaskRunner> ui_task_runner)
+ fml::RefPtr<fml::TaskRunner> ui_task_runner,
+ const std::string& channel)
: callback_(std::move(callback)),
- ui_task_runner_(std::move(ui_task_runner)) {}
+ ui_task_runner_(std::move(ui_task_runner)),
+ channel_(channel) {}
PlatformMessageResponseDart::~PlatformMessageResponseDart() {
if (!callback_.is_empty()) {
@@ -28,42 +63,16 @@
}
void PlatformMessageResponseDart::Complete(std::unique_ptr<fml::Mapping> data) {
- if (callback_.is_empty()) {
- return;
- }
- FML_DCHECK(!is_complete_);
- is_complete_ = true;
- ui_task_runner_->PostTask(fml::MakeCopyable(
- [callback = std::move(callback_), data = std::move(data)]() mutable {
- std::shared_ptr<tonic::DartState> dart_state =
- callback.dart_state().lock();
- if (!dart_state) {
- return;
- }
- tonic::DartState::Scope scope(dart_state);
-
- Dart_Handle byte_buffer =
- tonic::DartByteData::Create(data->GetMapping(), data->GetSize());
- tonic::DartInvoke(callback.Release(), {byte_buffer});
- }));
+ PostCompletion(std::move(callback_), ui_task_runner_, &is_complete_, channel_,
+ [data = std::move(data)] {
+ return tonic::DartByteData::Create(data->GetMapping(),
+ data->GetSize());
+ });
}
void PlatformMessageResponseDart::CompleteEmpty() {
- if (callback_.is_empty()) {
- return;
- }
- FML_DCHECK(!is_complete_);
- is_complete_ = true;
- ui_task_runner_->PostTask(
- fml::MakeCopyable([callback = std::move(callback_)]() mutable {
- std::shared_ptr<tonic::DartState> dart_state =
- callback.dart_state().lock();
- if (!dart_state) {
- return;
- }
- tonic::DartState::Scope scope(dart_state);
- tonic::DartInvoke(callback.Release(), {Dart_Null()});
- }));
+ PostCompletion(std::move(callback_), ui_task_runner_, &is_complete_, channel_,
+ [] { return Dart_Null(); });
}
} // namespace flutter
diff --git a/lib/ui/window/platform_message_response_dart.h b/lib/ui/window/platform_message_response_dart.h
index 79293ff..f290faf 100644
--- a/lib/ui/window/platform_message_response_dart.h
+++ b/lib/ui/window/platform_message_response_dart.h
@@ -22,11 +22,13 @@
protected:
explicit PlatformMessageResponseDart(
tonic::DartPersistentValue callback,
- fml::RefPtr<fml::TaskRunner> ui_task_runner);
+ fml::RefPtr<fml::TaskRunner> ui_task_runner,
+ const std::string& channel);
~PlatformMessageResponseDart() override;
tonic::DartPersistentValue callback_;
fml::RefPtr<fml::TaskRunner> ui_task_runner_;
+ const std::string channel_;
};
} // namespace flutter
diff --git a/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java b/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java
index d97b730..8a90964 100644
--- a/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java
+++ b/shell/platform/android/io/flutter/embedding/engine/dart/DartMessenger.java
@@ -312,8 +312,10 @@
int replyId,
long messageData) {
final DartMessengerTaskQueue taskQueue = (handlerInfo != null) ? handlerInfo.taskQueue : null;
+ TraceSection.beginAsyncSection("PlatformChannel ScheduleHandler on " + channel, replyId);
Runnable myRunnable =
() -> {
+ TraceSection.endAsyncSection("PlatformChannel ScheduleHandler on " + channel, replyId);
TraceSection.begin("DartMessenger#handleMessageFromDart on " + channel);
try {
invokeHandler(handlerInfo, message, replyId);
diff --git a/shell/platform/android/io/flutter/util/TraceSection.java b/shell/platform/android/io/flutter/util/TraceSection.java
index 0f61864..53c2889 100644
--- a/shell/platform/android/io/flutter/util/TraceSection.java
+++ b/shell/platform/android/io/flutter/util/TraceSection.java
@@ -8,18 +8,36 @@
import androidx.tracing.Trace;
public final class TraceSection {
+ private static String cropSectionName(@NonNull String sectionName) {
+ return sectionName.length() < 124 ? sectionName : sectionName.substring(0, 124) + "...";
+ }
+
/**
* Wraps Trace.beginSection to ensure that the line length stays below 127 code units.
*
* @param sectionName The string to display as the section name in the trace.
*/
public static void begin(@NonNull String sectionName) {
- sectionName = sectionName.length() < 124 ? sectionName : sectionName.substring(0, 124) + "...";
- Trace.beginSection(sectionName);
+ Trace.beginSection(cropSectionName(sectionName));
}
/** Wraps Trace.endSection. */
public static void end() throws RuntimeException {
Trace.endSection();
}
+
+ /**
+ * Wraps Trace.beginAsyncSection to ensure that the line length stays below 127 code units.
+ *
+ * @param sectionName The string to display as the section name in the trace.
+ * @param cookie Unique integer defining the section.
+ */
+ public static void beginAsyncSection(String sectionName, int cookie) {
+ Trace.beginAsyncSection(cropSectionName(sectionName), cookie);
+ }
+
+ /** Wraps Trace.endAsyncSection to ensure that the line length stays below 127 code units. */
+ public static void endAsyncSection(String sectionName, int cookie) {
+ Trace.endAsyncSection(cropSectionName(sectionName), cookie);
+ }
}
diff --git a/shell/platform/darwin/ios/platform_message_handler_ios.mm b/shell/platform/darwin/ios/platform_message_handler_ios.mm
index 9e316cc..7f6efcd6 100644
--- a/shell/platform/darwin/ios/platform_message_handler_ios.mm
+++ b/shell/platform/darwin/ios/platform_message_handler_ios.mm
@@ -4,9 +4,12 @@
#import "flutter/shell/platform/darwin/ios/platform_message_handler_ios.h"
+#import "flutter/fml/trace_event.h"
#import "flutter/shell/platform/darwin/common/buffer_conversions.h"
#import "flutter/shell/platform/darwin/common/framework/Headers/FlutterBinaryMessenger.h"
+static uint64_t platform_message_counter = 1;
+
@protocol FlutterTaskQueue
- (void)dispatch:(dispatch_block_t)block;
@end
@@ -61,8 +64,12 @@
data = ConvertMappingToNSData(message->releaseData());
}
+ uint64_t platform_message_id = platform_message_counter++;
+ TRACE_EVENT_ASYNC_BEGIN1("flutter", "PlatformChannel ScheduleHandler", platform_message_id,
+ "channel", message->channel().c_str());
dispatch_block_t run_handler = ^{
handler(data, ^(NSData* reply) {
+ TRACE_EVENT_ASYNC_END0("flutter", "PlatformChannel ScheduleHandler", platform_message_id);
// Called from any thread.
if (completer) {
if (reply) {