Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WriteBytesAsync with Uint8Array is slower than WebView1 counterpart. #3486

Open
vagisha-nidhi195 opened this issue May 15, 2023 · 6 comments
Assignees
Labels
bug Something isn't working tracked We are tracking this work internally.

Comments

@vagisha-nidhi195
Copy link

vagisha-nidhi195 commented May 15, 2023

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

  1. 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
  2. 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

AB#45973938

@vagisha-nidhi195 vagisha-nidhi195 added the bug Something isn't working label May 15, 2023
@novac42
Copy link
Contributor

novac42 commented May 16, 2023

Thanks for reporting the issue. I've assigned this to a dev who can help follow up on this.

@david-risney david-risney added the tracked We are tracking this work internally. label May 16, 2023
@david-risney
Copy link
Contributor

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!

@emre-ozgu
Copy link

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

@vagisha-nidhi195
Copy link
Author

@david-risney Any update on this one? We are really looking forward to getting the read/write bytes issues fixed.

@david-risney
Copy link
Contributor

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.

@yildirimcagri-msft
Copy link
Member

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.

@aluhrs13 aluhrs13 changed the title WriteBytesAsync with Uint8Array results in Interface not supported error WriteBytesAsync with Uint8Array is slower than WebView1 counterpart. May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working tracked We are tracking this work internally.
Projects
None yet
Development

No branches or pull requests

5 participants