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

Add support for keeping pooling allocator pages resident #5207

Merged

Commits on Nov 4, 2022

  1. Add support for keeping pooling allocator pages resident

    When new wasm instances are created repeatedly in high-concurrency
    environments one of the largest bottlenecks is the contention on
    kernel-level locks having to do with the virtual memory. It's expected
    that usage in this environment is leveraging the pooling instance
    allocator with the `memory-init-cow` feature enabled which means that
    the kernel level VM lock is acquired in operations such as:
    
    1. Growing a heap with `mprotect` (write lock)
    2. Faulting in memory during usage (read lock)
    3. Resetting a heap's contents with `madvise` (read lock)
    4. Shrinking a heap with `mprotect` when reusing a slot (write lock)
    
    Rapid usage of these operations can lead to detrimental performance
    especially on otherwise heavily loaded systems, worsening the more
    frequent the above operations are. This commit is aimed at addressing
    the (2) case above, reducing the number of page faults that are
    fulfilled by the kernel.
    
    Currently these page faults happen for three reasons:
    
    * When memory is first accessed after the heap is grown.
    * When the initial linear memory image is accessed for the first time.
    * When the initial zero'd heap contents, not part of the linear memory
      image, are accessed.
    
    This PR is attempting to address the latter of these cases, and to a
    lesser extent the first case as well. Specifically this PR provides the
    ability to partially reset a pooled linear memory with `memset` rather
    than `madvise`. This is done to have the same effect of resetting
    contents to zero but namely has a different effect on paging, notably
    keeping the pages resident in memory rather than returning them to the
    kernel. This means that reuse of a linear memory slot on a page that was
    previously `memset` will not trigger a page fault since everything
    remains paged into the process.
    
    The end result is that any access to linear memory which has been
    touched by `memset` will no longer page fault on reuse. On more recent
    kernels (6.0+) this also means pages which were zero'd by `memset`, made
    inaccessible with `PROT_NONE`, and then made accessible again with
    `PROT_READ | PROT_WRITE` will not page fault. This can be common when a
    wasm instances grows its heap slightly, uses that memory, but then it's
    shrunk when the memory is reused for the next instance. Note that this
    kernel optimization requires a 6.0+ kernel.
    
    This same optimization is furthermore applied to both async stacks with
    the pooling memory allocator in addition to table elements. The defaults
    of Wasmtime are not changing with this PR, instead knobs are being
    exposed for embedders to turn if they so desire. This is currently being
    experimented with at Fastly and I may come back and alter the defaults
    of Wasmtime if it seems suitable after our measurements.
    alexcrichton committed Nov 4, 2022
    Configuration menu
    Copy the full SHA
    9f4dfcd View commit details
    Browse the repository at this point in the history