Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c8e4c69

Browse files
Avoid copying the contents of large platform message responses (#4947)
Assets are loaded via platform messages, and currently asset payloads are being copied into Dart typed data buffers. This change uses external typed data objects that wrap the existing buffer if copying would be expensive. See flutter/flutter#16291
1 parent 5ff5272 commit c8e4c69

File tree

3 files changed

+49
-30
lines changed

3 files changed

+49
-30
lines changed

lib/ui/window/platform_message_response_dart.cc

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,41 @@
77
#include <utility>
88

99
#include "flutter/common/threads.h"
10+
#include "flutter/lib/ui/window/window.h"
1011
#include "lib/fxl/functional/make_copyable.h"
1112
#include "lib/tonic/dart_state.h"
1213
#include "lib/tonic/logging/dart_invoke.h"
1314

1415
namespace blink {
1516

17+
namespace {
18+
19+
// Avoid copying the contents of messages beyond a certain size.
20+
const int kMessageCopyThreshold = 1000;
21+
22+
void MessageDataFinalizer(void* isolate_callback_data,
23+
Dart_WeakPersistentHandle handle,
24+
void* peer) {
25+
std::vector<uint8_t>* data = reinterpret_cast<std::vector<uint8_t>*>(peer);
26+
delete data;
27+
}
28+
29+
Dart_Handle WrapByteData(std::vector<uint8_t> data) {
30+
if (data.size() < kMessageCopyThreshold) {
31+
return ToByteData(data);
32+
} else {
33+
std::vector<uint8_t>* heap_data = new std::vector<uint8_t>(std::move(data));
34+
Dart_Handle data_handle = Dart_NewExternalTypedData(
35+
Dart_TypedData_kByteData, heap_data->data(), heap_data->size());
36+
DART_CHECK_VALID(data_handle);
37+
Dart_NewWeakPersistentHandle(data_handle, heap_data, heap_data->size(),
38+
MessageDataFinalizer);
39+
return data_handle;
40+
}
41+
}
42+
43+
} // anonymous namespace
44+
1645
PlatformMessageResponseDart::PlatformMessageResponseDart(
1746
tonic::DartPersistentValue callback)
1847
: callback_(std::move(callback)) {}
@@ -38,19 +67,7 @@ void PlatformMessageResponseDart::Complete(std::vector<uint8_t> data) {
3867
return;
3968
tonic::DartState::Scope scope(dart_state);
4069

41-
Dart_Handle byte_buffer =
42-
Dart_NewTypedData(Dart_TypedData_kByteData, data.size());
43-
DART_CHECK_VALID(byte_buffer);
44-
45-
void* buffer;
46-
intptr_t length;
47-
Dart_TypedData_Type type;
48-
DART_CHECK_VALID(
49-
Dart_TypedDataAcquireData(byte_buffer, &type, &buffer, &length));
50-
FXL_CHECK(type == Dart_TypedData_kByteData);
51-
FXL_CHECK(static_cast<size_t>(length) == data.size());
52-
memcpy(buffer, data.data(), length);
53-
Dart_TypedDataReleaseData(byte_buffer);
70+
Dart_Handle byte_buffer = WrapByteData(std::move(data));
5471
tonic::DartInvoke(callback.Release(), {byte_buffer});
5572
}));
5673
}

lib/ui/window/window.cc

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,6 @@ using tonic::ToDart;
2222
namespace blink {
2323
namespace {
2424

25-
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
26-
Dart_Handle data_handle =
27-
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
28-
if (Dart_IsError(data_handle))
29-
return data_handle;
30-
31-
Dart_TypedData_Type type;
32-
void* data = nullptr;
33-
intptr_t num_bytes = 0;
34-
FXL_CHECK(!Dart_IsError(
35-
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));
36-
37-
memcpy(data, buffer.data(), num_bytes);
38-
Dart_TypedDataReleaseData(data_handle);
39-
return data_handle;
40-
}
41-
4225
void DefaultRouteName(Dart_NativeArguments args) {
4326
std::string routeName =
4427
UIDartState::Current()->window()->client()->DefaultRouteName();
@@ -119,6 +102,23 @@ void _RespondToPlatformMessage(Dart_NativeArguments args) {
119102

120103
} // namespace
121104

105+
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer) {
106+
Dart_Handle data_handle =
107+
Dart_NewTypedData(Dart_TypedData_kByteData, buffer.size());
108+
if (Dart_IsError(data_handle))
109+
return data_handle;
110+
111+
Dart_TypedData_Type type;
112+
void* data = nullptr;
113+
intptr_t num_bytes = 0;
114+
FXL_CHECK(!Dart_IsError(
115+
Dart_TypedDataAcquireData(data_handle, &type, &data, &num_bytes)));
116+
117+
memcpy(data, buffer.data(), num_bytes);
118+
Dart_TypedDataReleaseData(data_handle);
119+
return data_handle;
120+
}
121+
122122
WindowClient::~WindowClient() {}
123123

124124
Window::Window(WindowClient* client) : client_(client) {}

lib/ui/window/window.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ class DartLibraryNatives;
2121
namespace blink {
2222
class Scene;
2323

24+
Dart_Handle ToByteData(const std::vector<uint8_t>& buffer);
25+
2426
class WindowClient {
2527
public:
2628
virtual std::string DefaultRouteName() = 0;

0 commit comments

Comments
 (0)