-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Allocating a >2GB pointer only seems to work when MALLOC='emmalloc' flag is set. Why isn't this documented anywhere? #17747
Comments
This certainly reads like a bug. Both emmalloc and the default dlmalloc allocators should work with >2GB allocations to my understanding. Not sure why dlmalloc would fail on this, since it is a very "old" allocator used in lots of projects, and haven't ever heard that it would have a limitation like this by design. Maybe there is something off with how Emscripten interacts with dlmalloc that does not work quite right. Minimal repros welcome (does it fail on a straightforward Furthermore, In WASM64 mode they should both also work with >4GB allocations (maybe not yet today since Wasm64 is still in development, but modulo any current bugs or missing items there) |
Yes, I've tried to simplify the reproduction, but only using JavaScript (no calls at all to WASM methods). I've exported const m = await initializeWasmModule() // code to initialize the module is omitted
const ptr = m._malloc(2147473648)
console.log(ptr)
Reducing the size allocated from Since I'm running on Windows there's a possibility this is somehow platform related, but I'm not sure. I haven't yet tried on other platforms. Edit: with |
I was able to simplify and reproduce this in WSL2 Linux ( Here's an (almost) minimal reproduction case:
PROJ=wasm-allocation-test
EMCCFLAGS=-s WASM=1 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4GB -s MALLOC='dlmalloc' -s EXPORTED_FUNCTIONS="['_malloc']" -s MODULARIZE=1 -s EXPORT_NAME="TestModule"
all: empty.c
emcc $(EMCCFLAGS) -O0 -o $(PROJ).js $^
.PHONY: clean
clean:
rm -f $(PROJ).js $(PROJ).wasm
async function testLargeAllocation() {
const instance = (await import("./wasm-allocation-test.js")).default;
const m = await instance()
const ptr = m._malloc(2147483648 + 1000000);
console.log(ptr);
}
testLargeAllocation()
It exhibits the same behavoir (fails with |
I also have this issue. I'm able to allocate more than 2GB if I do it by requesting several <=2GB chunks but I'm not able to allocate a single >2GB chunk. Everything works fine if I use emmalloc instead of dlmalloc. I'm using 3.1.23. |
After some more testing, it seems like this issue only happens if the heap needs to be resized during the malloc call. If it's already larger than 2GB (e.g. by allocating and then freeing several < 2GB chunks), then I'm able to call malloc with > 2GB successfully. |
@miwelc Interesting. Could be a bug in dlmalloc then in a code path that grows memory using sbrk. It won't do that if you've already allocated over 2GB. Debugging into dlmalloc is one option (maybe for code paths around sbrk). Another might be to see if upgrading dlmalloc fixes this - it could be a fixed bug. |
After some digging in dlmalloc source code, I've seen that all allocations that rely on sbrk have this guard: #define MAX_SIZE_T (~(size_t)0)
#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) If I'm not mistaken, |
I've actually tested this and confirmed that by changing
If Emscripten's |
Good find @miwelc ! Yes, emscripten's |
Sure, I'll open a PR. |
The argument to sbrk is currently signed, but we immediately cast it to unsigned: Line 55 in 264b61d
So yes it should be safe to use the full 32bits of range for the increment. I'm not sure I understand the Regardless, shouldn't dlmalloc just call |
We've moved the conversation to the PR (#18055) but in order to keep last question answered here: |
I'm using latest
emscripten
(3.1.20
), nodex64 16.17.0
on Win10 (x64).emcc
compilation is executed within WSL2 (Ubuntu 22.04.1 LTS
).I've spent some time trying to get my code (written in C) to allocate a single large matrix that may be several gigabytes in size (nothing else of significant size is allocated prior to this).
Using flags:
Didn't work when the allocated size was greater than 2GB.
After some trial and error. Going as deep as inspecting the source files, I found an option that changes the allocator from the default
dlmalloc
toemmaloc
. Once I changed the command line to:it worked.
Is this intended behavior? Why isn't this documented anywhere?
The most prominent Google result is a post on the V8 blog that mentions the
MAXIMUM_MEMORY
flag, but doesn't say anything aboutMALLOC
?The text was updated successfully, but these errors were encountered: