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

iOS mobile phone encountered "Failed to create memory" problem when loading .wasm #4343

Closed
zhangtianhao1230 opened this issue Dec 5, 2023 · 11 comments
Assignees
Labels
🎉 enhancement New feature! 📦 lib-vm About wasmer-vm priority-low Low priority issue ❓ question I've a question!
Milestone

Comments

@zhangtianhao1230
Copy link

zhangtianhao1230 commented Dec 5, 2023

Summary

iOS mobile phone encountered "Failed to create memory" problem when loading .wasm

Additional details

Provide any additional details here.
I tested the results of loading .wat and .wasm on an iOS phone based on the examples in the project "examples". The summary said that .wat could be loaded normally, but an error was encountered when loading .wasm.

  1. When executing the reference code of wasi_manual_setup.rs. In order to get the specific error, I made a modification. Specifically:
    let instance: Instance = match Instance::new(&mut store, &module, &import_object) { Ok(instance) => instance, Err(error) => { eprintln!("Instanc fail,Error: {:?}", error); return Err(anyhow::Error::new(error)); } };
  2. Put the code that is basically the same as that in the wasi_manual_setup.rs file into a new project, and execute ''cargo build --target=aarch64-apple-ios --release" to generate an .a static library.
    When placed in an iOS project and executed, an error message "Link(Resource("Failed to create memory: Error when allocating memory: Cannot allocate memory (os error 12)"))"
    What can I do to get rid of this error
@zhangtianhao1230 zhangtianhao1230 added the ❓ question I've a question! label Dec 5, 2023
@Michael-F-Bryan
Copy link
Contributor

It sounds like you are running into a limitation imposed by iOS, namely that programs aren't allowed to generate machine code at runtime and execute it. The reason you see the Instance::new() erroring out is because that's the first thing that runs the iOS syscall that prevents this (I think it'll be something related to mmap()).

You may have some luck by pre-compiling the WebAssembly module on your own laptop and loading it with Artifact::deserialize(), but I've never tried this myself.

@Michael-F-Bryan Michael-F-Bryan added bug Something isn't working 📦 lib-vm About wasmer-vm priority-low Low priority issue labels Dec 12, 2023
@Michael-F-Bryan Michael-F-Bryan added this to the v4.x milestone Dec 12, 2023
@Michael-F-Bryan Michael-F-Bryan added 🎉 enhancement New feature! and removed bug Something isn't working labels Dec 12, 2023
@oliveeyay
Copy link

oliveeyay commented Dec 12, 2023

Hello,

Interestingly, I am seeing the same issue on a project I'm working on right now.

I have a solution that works for a "Full" iOS app, but not for an iOS App Clip. Some explanations:

  • You can add entitlement/capabilities to Full apps on iOS
  • One of these capabilities is called "Extended Virtual Addressing" which extends the number of addresses that can be referenced from an application
  • With this capability on, my wasm program runs perfectly. Without, it crashes with the same exact error as @zhangtianhao1230

Now, the problem with App Clips is that they have access to a subset of these capabilities, and "Extended Virtual Addressing" is obviously not one of them. I really need the wasm program to run as part of the App Clip too.

I tried the Tunables solution to limit the max memory to 36 pages (amongst other values, up to the limit of 65k) as mentioned here #1360. Without any success unfortunately.

Our wasm program is also pre-compiled (using Cranelift right now, trying LLVM soon).

Would you have any ideas?
Are there some ways to limit the size of the Engine or the Pages reserved in advance? (despite Tunables)

@oliveeyay
Copy link

oliveeyay commented Dec 13, 2023

Hello again,

In some news, pre-compiling with LLVM (instead of Cranelift) doesn't help.

The VM still crashes with the same error Link(Resource("Failed to create memory: Error when allocating memory: Cannot allocate memory (os error 12)")).

I've read here and there that the VM allocates 4gb + 2gb when loading a program (mmap), is that still correct in the latest version (4.2.4)? Is there an easy way to tune these values?

iOS draws a hard line at 4gb per app, as we can see in the performance tools in XCode (the red zone is where an app would OOM). I.E. this wasmer memory pre-allocation seems to be a blocker to run on iOS right now. When increasing that capacity through special capacities, it works (the "Extended Virtual Addressing"). So it's not like Apple/iOS is refusing to run pre-compiled code. It's a blocker for many use-cases (App Clips, older iPhones, Apple refusing to grant extra capabilities that are normally meant for Games etc.).

PS: the program I'm trying to run is fairly small (~700kb) and shouldn't need 4gb + 2gb. If there is an easy way to configure both that would be ideal?

Here's a picture of the app's memory before the crash (best guess is that it goes from 40mb directly to over the 4gb limit, as it crashes directly and I can't see the heap anymore):

Screenshot 2023-12-12 at 19 34 28

@oliveeyay
Copy link

As this is a pretty urgent blocker on my project (a blocker for iOS, as it runs fine on Android), I could propose to make an open-source iOS repository that reproduces this error?

Maybe as a way for you to reproduce and maybe if you have some ideas around how to configure the wasmer VM differently?

You would just need a MacOS machine to run that XCode project.

@oliveeyay
Copy link

Hello @Michael-F-Bryan

I created an Open-Source project that reproduces the issue: https://github.com/oliveeyay/SwiftWasmer
There are instructions on how to build and test this project in the README.

It uses some simple examples that you can launch through various buttons:

  1. A sum function loaded from a text wat format (working in all situations)
  2. A sum function loaded from a wasm binary format (working in all situations)
  3. A memory.fill call that fills a Page of bytes (not working on iOS)
  4. A memory example that tries to read and fill pages (not working on iOS) - built after https://github.com/wasmerio/wasmer/blob/master/examples/memory.rs

The last two examples are not working on iOS natively.
They can work though, for instance by giving your app special entitlement that impacts the memory usage of your app ("Extended Virtual Addressing"). Unfortunately, these kinds of entitlement are only given to specific use cases (games, etc.) and are not available at all in certain other use cases (App Clip, etc.).

Would you be able to help figure out this issue @Michael-F-Bryan ?

@syrusakbary
Copy link
Member

Hey @oliveeyay, thanks for following up on the issue.

I'd love to follow up with a meeting to see how we can help further (I assume you are doing this work as part of Solana?). Feel free to create a meeting in https://cal.com/syrus to follow up

@oliveeyay
Copy link

Hello @syrusakbary

Thanks for the quick response!

Yeah, that's part of one project at Solana indeed.

Booked for tomorrow, thanks again.

@zhangtianhao1230
Copy link
Author

zhangtianhao1230 commented Dec 20, 2023

Hello @Michael-F-Bryan

I created an Open-Source project that reproduces the issue: https://github.com/oliveeyay/SwiftWasmer There are instructions on how to build and test this project in the README.

It uses some simple examples that you can launch through various buttons:

  1. A sum function loaded from a text wat format (working in all situations)
  2. A sum function loaded from a wasm binary format (working in all situations)
  3. A memory.fill call that fills a Page of bytes (not working on iOS)
  4. A memory example that tries to read and fill pages (not working on iOS) - built after https://github.com/wasmerio/wasmer/blob/master/examples/memory.rs

The last two examples are not working on iOS natively. They can work though, for instance by giving your app special entitlement that impacts the memory usage of your app ("Extended Virtual Addressing"). Unfortunately, these kinds of entitlement are only given to specific use cases (games, etc.) and are not available at all in certain other use cases (App Clip, etc.).

Would you be able to help figure out this issue @Michael-F-Bryan ?

hi @oliveeyay Can you provide an oc project for your open source reproducible demonstration? I would be very grateful if you could take the time to provide it.

@zhangtianhao1230
Copy link
Author

It sounds like you are running into a limitation imposed by iOS, namely that programs aren't allowed to generate machine code at runtime and execute it. The reason you see the Instance::new() erroring out is because that's the first thing that runs the iOS syscall that prevents this (I think it'll be something related to mmap()).

You may have some luck by pre-compiling the WebAssembly module on your own laptop and loading it with Artifact::deserialize(), but I've never tried this myself.

hi @Michael-F-Bryan

It sounds like you are running into a limitation imposed by iOS, namely that programs aren't allowed to generate machine code at runtime and execute it. The reason you see the Instance::new() erroring out is because that's the first thing that runs the iOS syscall that prevents this (I think it'll be something related to mmap()).

You may have some luck by pre-compiling the WebAssembly module on your own laptop and loading it with Artifact::deserialize(), but I've never tried this myself.

hi @Michael-F-Bryan Have we released a new fixed version for this case? thanks

@oliveeyay
Copy link

oliveeyay commented Jan 4, 2024

Hey y'all,

@zhangtianhao1230 @Michael-F-Bryan @syrusakbary

After chatting with Syrus, I experimented with the Tunables API and 2 solutions are working. Based on your needs, you might want to use one or the other:

  • Using a limited static memory (512mb was a good balance between performance and memory size in my tests, i.e. specific to my wasm program)
  • Using a dynamic memory style (less performant)

Here is a reproducer open source project that contains both solutions, alongside instructions on how to build etc.: https://github.com/oliveeyay/SwiftWasmer

Additional note: since JIT-compiling is unofficially forbidden on iOS, I would advise you to use a headless mode with Wasmer (i.e. ahead of time compilation) to avoid issues with the approval process on the App Store.

@xdoardo
Copy link
Contributor

xdoardo commented Oct 17, 2024

iOS is going to be supported in Wasmer 5.0, which introduces interpreters. We are in the process of merging the release PR into main; after that, users will be able to test and use wasmer on their iOS devices.

@xdoardo xdoardo closed this as completed Oct 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🎉 enhancement New feature! 📦 lib-vm About wasmer-vm priority-low Low priority issue ❓ question I've a question!
Projects
None yet
Development

No branches or pull requests

5 participants