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

[browser][mt] Update memory views after growth, refactor string processing, fix SharedArrayBuffer detection #86664

Merged
merged 17 commits into from
May 28, 2023

Conversation

IsaMorphic
Copy link
Contributor

@IsaMorphic IsaMorphic commented May 23, 2023

"memory pooling or reclamation mechanism that they use internally that causes SharedArrayBuffer to cross the iframe boundary"

  • test for SharedArrayBuffer via buffer[Symbol.toStringTag] === "SharedArrayBuffer"
  • added copyBufferIfNecessary helper
    • the method is NOOP in non-threaded build
  • added receiveWorkerHeapViews
    • the method is NOOP in non-threaded build
  • replaced Module.HEAPxx with new localHeapViewXXX()
    • which calls receiveWorkerHeapViews and produces updated short lived "local" view
  • added -s TEXTDECODER=0 emcc linker flag for MT build
  • wrap Module.UTF8ArrayToString and Module.UTF8ToString with our own utf8ToString and decodeUTF8
    • this will copy the bytes and use TextDecoder for longer strings instead of emscripten byte-by-byte loop
  • move code into encodeUTF8 and utf8ToStringRelaxed of strings.ts
  • prefer HEAPU8 over HEAP8 for code consistency
  • string.ts refactoring

Fixes #86696
Fixes #86642

Related issues:
emscripten-core/emscripten#15217

…ffer from different JavaScript realm

When performing tasks such as allocating or marshalling large amounts of memory in multithreaded .NET land, inconsistent and frequent crashing behavior is exhibited. 

Related issues: 
emscripten-core/emscripten#15217
https://github.com/dotnet/aspnetcore/issues/48390
@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label May 23, 2023
@dotnet-issue-labeler dotnet-issue-labeler bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 23, 2023
@IsaMorphic
Copy link
Contributor Author

@dotnet-policy-service agree

@kg
Copy link
Member

kg commented May 23, 2023

Thanks for your contribution! If I understand correctly, this instanceof bug affects scenarios involving iframes because the iframe is a different realm and has its own builtins like Array and SharedArrayBuffer, right? So any case where we are using instanceof is potentially broken in that case, which is what motivates APIs like Array.isArray.

@IsaMorphic
Copy link
Contributor Author

Hi @kg!

That's exactly the scenario I came across that motivated this fix. I'll get to work right away on a solution that avoids the call to toString 😁

I'm glad to help!

@pavelsavara
Copy link
Member

How could dotnet wasm linear memory come from iframe ?
Are we talking about 2 runtimes sharing memory across the iframe boundary ?

I would appreciate small demo project which reproduces the issue before we merge this.
Adapting one of the samples would be ideal.

Possibly related issue #86642

@ghost
Copy link

ghost commented May 24, 2023

Tagging subscribers to 'arch-wasm': @lewing
See info in area-owners.md if you want to be subscribed.

Issue Details

When performing tasks such as allocating or marshalling large amounts of memory in multithreaded .NET land, inconsistent and frequent crashing behavior is exhibited.

I adapted a fix to this issue from this PR in the emscripten repository:
emscripten-core/emscripten#16994

Related issues:
emscripten-core/emscripten#15217
#86696

Author: IsaMorphic
Assignees: -
Labels:

arch-wasm, area-System.Runtime.InteropServices.JavaScript, community-contribution, needs-area-label

Milestone: -

@vcsjones vcsjones removed the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label May 24, 2023
IsaMorphic added a commit to IsaMorphic/runtime-wasmfix that referenced this pull request May 24, 2023
@IsaMorphic
Copy link
Contributor Author

IsaMorphic commented May 24, 2023

@pavelsavara
To answer your question, yes: in my implementation specific use case, I am using a Blazor app as an embeddable image renderer to demonstrate a future product. In my application I am using 2 or more runtimes per page (each in their own iframe). However, it seems (from the related emscripten bug) that all modern browsers might have some type of memory pooling or reclamation mechanism that they use internally that causes buffers to cross the iframe boundary. Though it still could be misuse on the part of the .net runtime, as well :P

Please see the latest commit on my fork's broken-sample branch. Use the typical launch commands for the browser-threading-minimal sample, but make sure to browse to http://localhost:<port>/embeds.html and read the text on the page. This updated sample replicates the issue extremely consistently.

I have not tried to see if my patch helps, as I have not built the runtime with the -sTEXTDECODER=0 flag and tested it in this way yet.

Hope this is helpful.

Update:
I've just tried out my sample with the current patchset of my PR + full runtime build with export EMCC_CFLAGS="-sTEXTDECODER=0" There's still errors of the same vein as we've been discussing at startup, only now it is inside dotnet.native.js and it is consistently generated from the same callsite. Otherwise there are no more errors of this nature at runtime.

image

I don't know where in the code this corresponds to. If someone can point me to it so I can update the file with the same Symbol.toStringTag fix that would be very helpful. Thanks!

@pavelsavara
Copy link
Member

UTF8ArrayToString is emscripten method and the issue is the same emscripten-core/emscripten#18034
TEXTDECODER=0 should have fixed that for you.

"memory pooling or reclamation mechanism that they use internally that causes buffers to cross the iframe boundary" could you please point me to more details about it ?

@pavelsavara
Copy link
Member

Also, if there is buffer reuse across iframes, it should also manifest without threads, right ?
We have iframe based benchmark which we run daily. I don't remember such issue to manifest there.

@radekdoulik would we capture/notice the error if one of the AppStart measures failed to start the runtime in the iframe ?

@pavelsavara pavelsavara changed the title Fix crashing bug in StringDecoder.decode when accessing SharedArrayBuffer from different JavaScript realm Fix crashing bug in StringDecoder.decode when accessing SharedArrayBuffer from different JavaScript realm/iframe May 25, 2023
@pavelsavara
Copy link
Member

I get it now, in our benchmark it's not a SharedArrayBuffer. I guess we should create MT flavor of the benchmark soon anyway.

@pavelsavara
Copy link
Member

Please see the latest commit on my fork's broken-sample branch.

main...IsaMorphic:runtime-wasmfix:broken-sample

I will have look soon, probably next week. Thanks a lot!

I would still love to read about how this is not a browser bug. :-D

@pavelsavara
Copy link
Member

I used your sample and indeed I can reproduce it.
image

I will push more comprehensive fix into this PR

@pavelsavara
Copy link
Member

I processed further feedback from @kg about not calling updateGrowableHeapViews() from tight loops.

While doing that I noticed that we have too many loops where we convert strings with different encodings, so I moved all of it into string.ts.
And while I worked on that I dropped StringDecoder class because it was not helping anything.
I dropped few legacy methods and renamed the rest to camelCase.

@ilonatommy I touched some of the hybrid locale stuff, please have look.

There is bit of risk that this change will introduce perf regression, but it was that already yesterday.
@radekdoulik could you please run benchmark on this before I merge it ?

@pavelsavara
Copy link
Member

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara pavelsavara changed the title Fix crashing bug in StringDecoder.decode when accessing SharedArrayBuffer from different JavaScript realm/iframe [browser][mt] Update memory views after growth, refactor string processing, fix SharedArrayBuffer detection May 26, 2023
@pavelsavara
Copy link
Member

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

src/mono/wasm/runtime/debug.ts Outdated Show resolved Hide resolved
src/mono/wasm/runtime/memory.ts Outdated Show resolved Hide resolved
Copy link
Member

@ilonatommy ilonatommy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Globalization pointer math checked.

src/mono/wasm/runtime/hybrid-globalization/change-case.ts Outdated Show resolved Hide resolved
@pavelsavara
Copy link
Member

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara
Copy link
Member

/azp run runtime-wasm

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@pavelsavara pavelsavara merged commit 5b8437d into dotnet:main May 28, 2023
@pavelsavara
Copy link
Member

I guess this is that we eliminated bunch of checks in the non-MT string conversion.

image

https://radekdoulik.github.io/WasmPerformanceMeasurements/?startDate=2023-05-24T10%3A51%3A33.000Z&endDate=2023-05-29T21%3A06%3A42.000Z&tasks=%2CJSInterop

@ghost ghost locked as resolved and limited conversation to collaborators Jun 29, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
arch-wasm WebAssembly architecture area-System.Runtime.InteropServices.JavaScript community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Issues using Blazor Multithreading within iframes [browser][MT] Memory growth on worker could cause failure
7 participants