On 32-bit operating systems, we often run into issues where the address space is too fragmented, and complex web applications, such as games, are unable to allocate large contiguous memory regions, such as WASM heaps or asm.js. In addition to 32-bit address space, other OS process-bound resources can become exhausted, depending on the device and system.
This problem can be solved by User Agents loading the games into a fresh unfragmented process. Unfortunately, by the time the allocation has failed it is too late to change which process the load is performed in.
We would add a new response header, the Large-Allocation
response header. This
response header would tell the browser that the page being loaded is going to
want to perform a large allocation. This response header should not have any
semantic effect, except it may improve the page's chances to successfully
allocate a large memory allocation.
The User Agent MAY, when it believes that such a large allocation would fail, load the page in a new process. This new process would have a less fragmented address space, thus increasing the chance that the allocation would succeed.
The Large-Allocation
response header accepts an argument, which is the
expected size of the allocation to be performed, in megabytes. The value of 0 is
a special value which represents uncertainty as to what the size of the
allocation is. It should be assumed to be a large allocation. This information
can be used to avoid creating a new process when it would not be necessary, as
well as potentially reserve memory in the new process for the allocation.
A Large-Allocation response header on a document which is going to do an arbitrary large-size allocation.
Large-Allocation: 0
A Large-Allocation response header on a document which is going to do a 500MB allocation.
Large-Allocation: 500
NOTE: Megabytes were chosen for the units because a 1MB allocation isn't going to fail unless the address space is super fragmented, and so it felt silly to allow for precision smaller than that.
A cross-process navigation (a navigation during which the process which a
browsing context is running in changes), such as one which would be requested by
the Large-Allocation
response header, is not possible when there are other
non-child browsing contexts within the navigating browsing contexts'
unit of related similar-origin browsing contexts.
In the situation where there are other non-child browsing contexts within the navigating browsing contexts' unit of related browsing contexts, but not unit of related similar-origin browsing contexts, it is possible to perform a process-changing load, so long as cross-process window proxies are avaliable. I expect that most User Agents will be unable and/or unwilling to implement this for Large-Allocation response headers, at least initially. For that reason I would generally consider this situation to also be a situation where Large-Allocation is not supported.
Thus, we can generally say that User Agents will be unable to Large-Allocation cross process loads when they are loaded in an iframe, or when any other non-child browsing context has a reference to the active browsing context.
This means that operations which are performed by previous pages loaded within
the browsing context of the active page can impact the page's ability to
allocate memory, which is sub-optimal. For example, if a previously loaded
website within the current browsing context opened a window with <a target=_blank>
, or if the browsing context itself was opened with an opener
,
then the page loaded, potentially much later, would be unable to perform a
cross-process navigation.
This constraint can be relaxed by a form of window proxy isolation such as the per-origin isolation proposal. One of the goals of this proposal seems to be to make toplevel loads to an origin which is isolated able to be reliably performed in another process, which would mean that the User Agent could reliably create a new process when necessary to allow Large-Allocation load to succeed.
This is achieved through disowning all references to the document, which is desirable for security purposes, as it prevents other browsing contexts from navigating you.
The following are some examples of how references to a toplevel browsing context could leak to other non-child browsing contexts within its unit of related browsing contexts. Any of these references could prevent a document from being loaded with a cross-process load:
-
If the browsing context performing the load was opened by another browsing context, then the
window.opener
property acts as a mechanism for two-way communication between the current browsing context and its opener. This property would likely be nulled. -
If the browsing context performing the load previously opened another browsing context without
noopener
ornoreferrer
, then that browsing context has a reference to the navigating browsing context. These references cannot be remotely nulled, so it may instead be more convenient to make them appear 3rd-party, and make all operations performed on them into no-ops. -
If the browsing context performing the load was opened by another browsing context, the other browsing context, or one of its related browsing contexts, may have a reference to the navigating browsing context, either through the return value of
window.open
, or due to thesource
property of apostMessage
message. These references also cannot be remotely nulled, so they may become no-op dummy references.
For general memory-intensive WebAssembly applications which still use storage, and/or interactions with 3rd party authentication services, such as OAuth, it would be desirable to gain access to the window proxy isolation features of the per-origin isolation proposal, which allow for these Large-Allocation cross process loads to occur even if there are existing references to the navigating browsing context, without also isolating the origin with regards to storage.
This would mean that the only situation which would still inhibit performing a Large-Allocation cross process load for an isolated origin would be if the Large-Allocation document is loaded in an iframe, because isolation only works on toplevel documents.
In addition to supporting Large-Allocation loads, window proxy isolation also
enables other forms of cross process loads. For example, a window proxy isolated
document can reliably preload in a new process, ensuring faster page loads. It
could also, depending on the implementation, be used as a source of optimization
for the JavaScript JIT, by giving it the invariant that window
always aliases
the global object while script is executing.
It seems like a version of window proxy isolation without storage isolation could be very useful as a general good practice for ensuring that your origin is nice to the User Agent, giving it the chance to switch you between processes, render things more quickly, and potentially even improve javascript performance.
Can we move this to an officially named document, i.e., something that is not a secret gist?