Limiting WASM memory allocation as an embedder?

265 views
Skip to first unread message

Kenton Varda

unread,
Sep 11, 2018, 12:34:56 PM9/11/18
to v8-u...@googlegroups.com
Hi v8-users,

I noticed that WASM seems to ignore the ResourceConstraints I've set on my isolate -- a WebAssembly.Memory object can grow to far beyond the heap constraint I've set, and I don't see any constraint specific to WASM. The JS code can, of course, specify a maximum memory limit when creating the Memory object, but that's an API exposed to the script. As as embedder, I need to enforce my own constraint.

Relatedly, it appears that GetHeapStatistics() does not include WASM memory in the counts. As an embedder I need to keep track of the memory an isolate has allocated.

I've searched through v8.h and haven't been able to find any alternate APIs for these. Is there one I missed, or is this something I'll need to add myself?

-Kenton

Ben Noordhuis

unread,
Sep 11, 2018, 2:19:13 PM9/11/18
to v8-users
You should be able to control it with the `--wasm_max_mem_pages=...`
flag (expressed in multiples of 64k) that you can set with
`v8::V8::SetFlagsFromString()`. I don't think there is currently any
other way to configure it.

WASM allocations should be observable when you return a custom
`v8::PageAllocator*` from `v8::Platform::GetPageAllocator()`. Maybe
not ideal but hopefully workable.

You can probably also limit memory growth that way, by returning
nullptr when it's past a threshold, although not on a per-isolate
basis.

ken...@cloudflare.com

unread,
Sep 12, 2018, 7:14:17 PM9/12/18
to v8-users
Looking at the code, it looks like --wasm_max_mem_pages limits the size of a particular Memory object, but a script can always allocate multiple objects / create multiple instances. I need to limit the script's total memory usage...

I do need to track and limit per-isolate. But maybe I can use PageAllocator combined with keeping track of the current isolate using thread-locals? Or might it be called in background threads?

-Kenton

Deepti Gandluri

unread,
Sep 12, 2018, 10:32:42 PM9/12/18
to v8-users
If you are looking to track Wasm allocations, there is a counter on the Isolate that wasm memory allocations are registered with - V8.WasmAddressSpaceUsageMiB. The page allocator is the catch all for allocations, so that should work too. 

For GetHeapStatistics(), WasmMemory is accounted for under malloced memory, could you elaborate on the discrepancies that you are seeing? 

Ideally, Memory.Grow should honor the same resource constraints that a JSArrayBuffer allocation does, because it either adjusts the externally allocated memory, or allocates a new ArrayBuffer. The WasmMemoryTracker tracks wasm allocations, apart from the isolate counters, there is no public API for the WasmEngine right now. 

Kenton Varda

unread,
Sep 16, 2018, 9:29:57 PM9/16/18
to v8-u...@googlegroups.com
Hi Deepti,

Thanks for your response.

On Wed, Sep 12, 2018 at 7:32 PM, 'Deepti Gandluri' via v8-users <v8-u...@googlegroups.com> wrote:
If you are looking to track Wasm allocations, there is a counter on the Isolate that wasm memory allocations are registered with - V8.WasmAddressSpaceUsageMiB. The page allocator is the catch all for allocations, so that should work too. 

For GetHeapStatistics(), WasmMemory is accounted for under malloced memory, could you elaborate on the discrepancies that you are seeing? 

In real tests, I observe that malloced_memory is always 8192. Even after creating a large WebAssembly.Memory object and populating it, malloced_memory continues to return 8192. I'm not sure what this stat tracks, exactly, but it makes sense that it wouldn't count WebAssembly.Memory backing buffers since they are presumably not allocated with malloc().

It looks like external_memory() was recently added, and this actually measures WASM memory, which solves my problem. (And it looks like while I wait for external_memory() to land in stable, I can call AdjustAmountOfExternalAllocatedMemory(0) as an alternative way to get the same information.)
 
Ideally, Memory.Grow should honor the same resource constraints that a JSArrayBuffer allocation does, because it either adjusts the externally allocated memory, or allocates a new ArrayBuffer. The WasmMemoryTracker tracks wasm allocations, apart from the isolate counters, there is no public API for the WasmEngine right now. 

For now I've implemented a "patrolling" technique, where I kill an isolate after the fact if it uses too much memory. It would be great if a limit on external memory were added to ResourceConstraints and enforced upfront. If I find time I'll look into adding this and submitting a patch.

-Kenton
Reply all
Reply to author
Forward
0 new messages