Skip to content

Commit 5bdda32

Browse files
perf(macOS): avoid copying large protocol bodies (#1719)
* perf(macOS): avoid copying large protocol bodies * refatcor: mirage `NSData::initWithBytes_length` to `NSData::with_bytes` * Refine WKURLSchemeTask body handling * chore: comment on optimize buffer handling in start_task to reduce copying for larger responses * perf: reduce NO_COPY_DATA_THRESHOLD to 64 KB for improved buffer handling * perf: increase NO_COPY_DATA_THRESHOLD to 128 KB for improved buffer handling * update url_scheme_handler.rs Co-authored-by: Tony <[email protected]> * update macos-protocol-body-nocopy.md * cargo fmt * Remove unused `NO_COPY_DATA_THRESHOLD` --------- Co-authored-by: Tony <[email protected]> Co-authored-by: Tony <[email protected]>
1 parent 101d7ac commit 5bdda32

4 files changed

Lines changed: 14 additions & 12 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wry": patch
3+
---
4+
5+
On macOS, avoid an extra copy for owned custom protocol response bodies by transferring the body buffer into `NSData`.

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ objc2-core-foundation = { version = "0.3.0", default-features = false, features
138138
] }
139139
objc2-foundation = { version = "0.3.0", default-features = false, features = [
140140
"std",
141+
"block2",
141142
"objc2-core-foundation",
142143
"NSURLRequest",
143144
"NSURL",

src/wkwebview/class/url_scheme_handler.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
use std::{
66
borrow::Cow,
7-
ffi::{c_char, c_void, CStr},
7+
ffi::{c_char, CStr},
88
panic::AssertUnwindSafe,
99
ptr::NonNull,
1010
};
@@ -214,7 +214,7 @@ extern "C" fn start_task(
214214
check_webview_id_valid(webview_id)?;
215215
check_task_is_valid(&webview, task_key, task_uuid.clone())?;
216216

217-
let content = sent_response.body();
217+
let content_len = sent_response.body().len();
218218
// default: application/octet-stream, but should be provided by the client
219219
let wanted_mime = sent_response.headers().get(CONTENT_TYPE);
220220
// default to 200
@@ -231,7 +231,7 @@ extern "C" fn start_task(
231231
}
232232
headers.insert(
233233
&*NSString::from_str(CONTENT_LENGTH.as_str()),
234-
&*NSString::from_str(&content.len().to_string()),
234+
&*NSString::from_str(&content_len.to_string()),
235235
);
236236

237237
// add headers
@@ -264,15 +264,10 @@ extern "C" fn start_task(
264264
}))
265265
.map_err(|_e| crate::Error::CustomProtocolTaskInvalid)?;
266266

267-
// Send data
268-
let data = NSData::alloc();
269-
// MIGRATE NOTE: we copied the content to the NSData because content will be freed
270-
// when out of scope but NSData will also free the content when it's done and cause doube free.
271-
let data = NSData::initWithBytes_length(
272-
data,
273-
content.as_ptr() as *mut c_void,
274-
content.len(),
275-
);
267+
let data = match sent_response.into_body() {
268+
Cow::Owned(content) => NSData::from_vec(content),
269+
Cow::Borrowed(content) => NSData::with_bytes(content),
270+
};
276271

277272
// Check validity again
278273
check_webview_id_valid(webview_id)?;

0 commit comments

Comments
 (0)