WebView2Feedback
WebView2Feedback copied to clipboard
WriteBytesAsync with Uint8Array is slower than WebView1 counterpart.
Description
Windows.Storage.FileIO.WriteBytesAsync
takes in a file and byteBuffer https://learn.microsoft.com/en-us/uwp/api/windows.storage.fileio.writebytesasync?view=winrt-22621. With WebView2, passing Uint8Array(data) as unknown as number[]
results in Interface not supported error.
Windows.Storage.FileIO.WriteBytesAsync(file, new Uint8Array(data) as unknown as number[])
It works when you pass a shallow copy of the object using, but we should be able to directly pass the Uint8Array as it was supported in webview1. Array slicing adds additional delay to write operations.
Windows.Storage.FileIO.WriteBytesAsync(file, Array.prototype.slice.call(new Uint8Array(data)) as unknown as number[])
Version SDK: 1.0.1777-prerelease Framework: UWP/WinRT OS: Win10
Repro Steps
- Create a WinRT on UWP project with WebView2 following https://learn.microsoft.com/en-us/microsoft-edge/webview2/how-to/winrt-from-js?tabs=winui2%2Cwinrtcsharp
- Run the app. Open the DevTools console and try the following:
Windows.Storage.FileIO.WriteBytesAsync(file, new Uint8Array(data) as unknown as number[])
Output
Interface not supported
Screenshots
Additional context This works as it is in webview1, regressed in webview2
Thanks for reporting the issue. I've assigned this to a dev who can help follow up on this.
I've opened a tracking bug for this. If it worked with the previous WebView1's WinRT projection we should look at supporting it for WebView2 - thanks!
Adding on to this, passing a plain array using Array.prototype.slice.call(new Uint8Array(data)
or Array.from(new Uint8Array(data)
seems to make the Windows.Storage.FileIO.WriteBytesAsync
operation take much longer in general compared to WebView1, outside of the conversion as well. This especially makes writing larger files (e.g. ~15MB) infeasible on WebView2.
WebView1 - JavaScript Code:
let timeMs = Date.now();
Windows.Storage.FileIO.writeBytesAsync(file, new Uint8Array(data))
.then(() => console.log(`WriteBytesAsync took ${Date.now() - timeMs}ms - Data Size: ${data.byteLength / 1000 / 1000}MB`));
Output 1:
WriteBytesAsync took 31ms - Data Size: 0.53288MB
Output 2:
WriteBytesAsync took 114ms - Data Size: 18.551616000000002MB
WebView2 - JavaScript Code:
let timeMs = Date.now();
const dataArray = Array.from(new Uint8Array(data));
console.log(`Array.from took ${Date.now() - timeMs}ms - Data Size: ${data.byteLength / 1000 / 1000}MB`);
timeMs = Date.now();
Windows.Storage.FileIO.writeBytesAsync(file, dataArray)
.then(() => console.log(`WriteBytesAsync took ${Date.now() - timeMs}ms - Data Size: ${data.byteLength / 1000 / 1000}MB`));
Output 1:
Array.from took 34ms - Data Size: 0.53288MB
WriteBytesAsync took 2098ms - Data Size: 0.53288MB
Output 2:
Array.from took 800ms - Data Size: 18.551616000000003MB
WriteBytesAsync took 66655ms - Data Size: 18.551616000000003MB
@david-risney Any update on this one? We are really looking forward to getting the read/write bytes issues fixed.
Apologies, no good update yet.
The WinRT API will be slow in this case at least because the byte array is in JS and the WinRT API is in the host app. The call to write the bytes will serialize all the bytes in the JS byte array, send the request to the host app, deserialize it into a native byte array and then actually call the WinRT API in the host app process.
If you can keep the bytes in a WinRT object rather than a JS object then we won't have to serialize all bytes. I'm not sure if that's practical for this scenario.
Alternatively perhaps instead of calling into the WinRT API to write the bytes you could use the shared buffer API to get the bytes to the native host app side without needing to serialize the byte array.
Hi again, if the idea is to be able to read/write to some file in web content in WebView2 directly, you can now use the CoreWebView2.PostWebMessageAsJsonWithAdditionalObjects to share a FileSystemHandle directly to the web content from the app. Even a working WinRT API approach will not be as performant due to reasons stated above.
This should be fixed in runtimes 125.0.2500.0+. Thanks!