Skip to content

What constraints should be imposed on custom page sizes? #2

Description

@fitzgen

We have a few options for custom page sizes we can allow:

  1. Any arbitrary byte size, eg 12345
  2. Powers of two between 1 and 64KiB, inclusive
  3. Only allow the specific values 1 or 64KiB
  4. A minimum page size that is a multiple of common OS page sizes (e.g. 16KiB)
  5. A minimum page size that is a multiple of the largest memory accesses that Wasm can perform today

This issue exists for us to discuss these options and come to a resolution.

Previous Discussion

I will quote previous comments from the original design issue here to kick start discussion.

@rossberg said

I think restricting to at least powers of 2, like we already do with alignment, would be appropriate.

@titzer said

I think supporting all powers of 2 between 1 and 64KiB would be best from the spec perspective. For example, 256 and 4KiB seem particularly likely to trigger hardware-supported bounds checks in future engines and hardware platforms (I'm thinking 8-bit and 16-bit MCUs, as well as smaller pages on x86).

@eqrion said

is there some smaller page size than 64KiB that could reliably be at least as big as common OS page sizes?

@sunfishcode said

  • 16KiB may have emerged as a new sweet-spot "performance-portable page size". Should we embrace that, at the cost of relatively niche 64KiB HPC users?

  • 4KiB could potentially be too tempting as the "optimal for x86 and similar" option for some users. Should we try to resist that, and limit page sizes to [16B, 64KiB], [16B, 256B, 16KiB, 64KiB], or similar?

I suggested 16B as the lowest end there because the alignment concerns raised here are a good point; engines can align the base of linear memory as needed, however partially-out-of-bounds atomics seem worth avoiding.

@alexcrichton said

To provide possible fodder in the direction of "just powers of two" -- AFAIK multiplication/division are generally more expensive than shifts. Thinking from an LLVM/LLD/toolchain perspective somehow the source code is going to want to be able to say "what is the actual byte size of the memory growth that just happened" or "how many pages does this byte-size-request translate to in terms of growth".

Toolchains are going to need to express the ability to customize page sizes and, for example, the CG presentation today threw out the possibility of a C macro or LLVM builtin function. If this value could be completely arbitrary then that implies arbitrary division/multiplication in the toolchain going between pages and bytes. This could be constant-propagated by a frontend, but one of the possibilities of toolchain integration was "let the linker figure out the page size". At link-time it's quite late in the optimization pipeline so it's not as easy to optimize constant multiplication/division.

If, however, page sizes were always a power of two then the basic operation would be shifting left/right. That would enable deferring the known size of a page all the way to link time without too much theoretical cost in terms of performance.

@rossberg said

Address masking is another operation that only works with powers of two.

@fitzgen said

We could also encode the page size as n in 2^n which I think would save some LEB encoding bytes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions