Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

wasi-http: Remove extra task when reading bodies #7475

Merged
merged 1 commit into from
Nov 3, 2023

Conversation

alexcrichton
Copy link
Member

This commit is in the same spirit as #7461 and is aimed at removing an extra task when interoperating between WebAssembly and Hyper. The intention here is to ensure that when data is ready immediately a context switch between Tokio tasks isn't necessary. I'm still not sure why this context switch would tank performance so much.

The goal of this commit is to remove the Tokio task associated with reading bodies. Currently a task is spawned with two channels coming out: one for frames and one for trailers. Instead the body is now read directly when data frames are read and trailers are managed similarly. The interactions here are somewhat nontrivial due to the management of resources and how the body needs to jump from the body stream object to the trailers object, but it's overall not the worst thing in the world.

Locally on Linux this takes a "hello world" component which starts out by reading its HTTP body and then responds with a string from 6.7k rps locally via wasmtime serve to 16.8k rps. This restores the performance of wasi-http to be in-line with the historical SDK that Fermyon offered, for example, that's based on a custom HTTP interface. Note that these performance numbers use #7461 as a baseline.

This commit has a downside, however, that if the incoming body is not being subscribed to actively by the wasm then no activity will happen on the host. This is a function of poll isn't being actively watched unless subscribe's result is being actively watched via a wasm call to wasi:io/poll. Manual investigation of Hyper shows that this is probably ok for now since bodies are primarily channel-based which seems like the tasks doing the actual I/O are managed elsewhere. In that sense this shouldn't cause any immediate impact, but Hyper's situation in the future could change or my analysis could additionally be wrong. Given the performance benefits here though I'd be tempted to push in favor of this commit and handle "poll in the background" as necessary in the future if needed.

This commit is in the same spirit as bytecodealliance#7461 and is aimed at removing an
extra task when interoperating between WebAssembly and Hyper. The
intention here is to ensure that when data is ready immediately a
context switch between Tokio tasks isn't necessary. I'm still not sure
why this context switch would tank performance so much.

The goal of this commit is to remove the Tokio task associated with
reading bodies. Currently a task is spawned with two channels coming
out: one for frames and one for trailers. Instead the body is now read
directly when data frames are read and trailers are managed similarly.
The interactions here are somewhat nontrivial due to the management of
resources and how the body needs to jump from the body stream object to
the trailers object, but it's overall not the worst thing in the world.

Locally on Linux this takes a "hello world" component which starts out
by reading its HTTP body and then responds with a string from 6.7k rps
locally via `wasmtime serve` to 16.8k rps. This restores the performance
of wasi-http to be in-line with the historical SDK that Fermyon offered,
for example, that's based on a custom HTTP interface. Note that these
performance numbers use bytecodealliance#7461 as a baseline.

This commit has a downside, however, that if the incoming body is not
being subscribed to actively by the wasm then no activity will happen on
the host. This is a function of `poll` isn't being actively watched
unless `subscribe`'s result is being actively watched via a wasm call to
`wasi:io/poll`. Manual investigation of Hyper shows that this is
probably ok for now since bodies are primarily channel-based which seems
like the tasks doing the actual I/O are managed elsewhere. In that sense
this shouldn't cause any immediate impact, but Hyper's situation in the
future could change or my analysis could additionally be wrong. Given
the performance benefits here though I'd be tempted to push in favor of
this commit and handle "poll in the background" as necessary in the
future if needed.
@alexcrichton alexcrichton requested a review from a team as a code owner November 3, 2023 16:14
Ok(()) => {}
// TODO: same as above, shouldn't throw this error away.
Err(e) => tracing::warn!("dropping error {e}"),
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll note that this, and the above, are somewhat unrelated but also tangential changes since I was touching these types. The above task previously dropped the error and this task tried to forward it along. In both cases though the result of this task was never actually looked at as the handle was exclusively used to keep the task alive and that's it.

I've updated this so both tasks consistently drop the error. I don't know how to communicate this error through the WASI APIs myself.

@github-actions github-actions bot added the wasi Issues pertaining to WASI label Nov 3, 2023
@pchickey pchickey added this pull request to the merge queue Nov 3, 2023
Merged via the queue into bytecodealliance:main with commit 7fea4a4 Nov 3, 2023
18 checks passed
@alexcrichton alexcrichton deleted the http-direct-read branch November 4, 2023 16:51
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Nov 6, 2023
This commit is in the same spirit as bytecodealliance#7461 and is aimed at removing an
extra task when interoperating between WebAssembly and Hyper. The
intention here is to ensure that when data is ready immediately a
context switch between Tokio tasks isn't necessary. I'm still not sure
why this context switch would tank performance so much.

The goal of this commit is to remove the Tokio task associated with
reading bodies. Currently a task is spawned with two channels coming
out: one for frames and one for trailers. Instead the body is now read
directly when data frames are read and trailers are managed similarly.
The interactions here are somewhat nontrivial due to the management of
resources and how the body needs to jump from the body stream object to
the trailers object, but it's overall not the worst thing in the world.

Locally on Linux this takes a "hello world" component which starts out
by reading its HTTP body and then responds with a string from 6.7k rps
locally via `wasmtime serve` to 16.8k rps. This restores the performance
of wasi-http to be in-line with the historical SDK that Fermyon offered,
for example, that's based on a custom HTTP interface. Note that these
performance numbers use bytecodealliance#7461 as a baseline.

This commit has a downside, however, that if the incoming body is not
being subscribed to actively by the wasm then no activity will happen on
the host. This is a function of `poll` isn't being actively watched
unless `subscribe`'s result is being actively watched via a wasm call to
`wasi:io/poll`. Manual investigation of Hyper shows that this is
probably ok for now since bodies are primarily channel-based which seems
like the tasks doing the actual I/O are managed elsewhere. In that sense
this shouldn't cause any immediate impact, but Hyper's situation in the
future could change or my analysis could additionally be wrong. Given
the performance benefits here though I'd be tempted to push in favor of
this commit and handle "poll in the background" as necessary in the
future if needed.
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Nov 6, 2023
This commit is in the same spirit as bytecodealliance#7461 and is aimed at removing an
extra task when interoperating between WebAssembly and Hyper. The
intention here is to ensure that when data is ready immediately a
context switch between Tokio tasks isn't necessary. I'm still not sure
why this context switch would tank performance so much.

The goal of this commit is to remove the Tokio task associated with
reading bodies. Currently a task is spawned with two channels coming
out: one for frames and one for trailers. Instead the body is now read
directly when data frames are read and trailers are managed similarly.
The interactions here are somewhat nontrivial due to the management of
resources and how the body needs to jump from the body stream object to
the trailers object, but it's overall not the worst thing in the world.

Locally on Linux this takes a "hello world" component which starts out
by reading its HTTP body and then responds with a string from 6.7k rps
locally via `wasmtime serve` to 16.8k rps. This restores the performance
of wasi-http to be in-line with the historical SDK that Fermyon offered,
for example, that's based on a custom HTTP interface. Note that these
performance numbers use bytecodealliance#7461 as a baseline.

This commit has a downside, however, that if the incoming body is not
being subscribed to actively by the wasm then no activity will happen on
the host. This is a function of `poll` isn't being actively watched
unless `subscribe`'s result is being actively watched via a wasm call to
`wasi:io/poll`. Manual investigation of Hyper shows that this is
probably ok for now since bodies are primarily channel-based which seems
like the tasks doing the actual I/O are managed elsewhere. In that sense
this shouldn't cause any immediate impact, but Hyper's situation in the
future could change or my analysis could additionally be wrong. Given
the performance benefits here though I'd be tempted to push in favor of
this commit and handle "poll in the background" as necessary in the
future if needed.

Signed-off-by: Alex Crichton <alex@alexcrichton.com>
alexcrichton added a commit to alexcrichton/wasmtime that referenced this pull request Nov 8, 2023
This commit is in the same spirit as bytecodealliance#7461 and is aimed at removing an
extra task when interoperating between WebAssembly and Hyper. The
intention here is to ensure that when data is ready immediately a
context switch between Tokio tasks isn't necessary. I'm still not sure
why this context switch would tank performance so much.

The goal of this commit is to remove the Tokio task associated with
reading bodies. Currently a task is spawned with two channels coming
out: one for frames and one for trailers. Instead the body is now read
directly when data frames are read and trailers are managed similarly.
The interactions here are somewhat nontrivial due to the management of
resources and how the body needs to jump from the body stream object to
the trailers object, but it's overall not the worst thing in the world.

Locally on Linux this takes a "hello world" component which starts out
by reading its HTTP body and then responds with a string from 6.7k rps
locally via `wasmtime serve` to 16.8k rps. This restores the performance
of wasi-http to be in-line with the historical SDK that Fermyon offered,
for example, that's based on a custom HTTP interface. Note that these
performance numbers use bytecodealliance#7461 as a baseline.

This commit has a downside, however, that if the incoming body is not
being subscribed to actively by the wasm then no activity will happen on
the host. This is a function of `poll` isn't being actively watched
unless `subscribe`'s result is being actively watched via a wasm call to
`wasi:io/poll`. Manual investigation of Hyper shows that this is
probably ok for now since bodies are primarily channel-based which seems
like the tasks doing the actual I/O are managed elsewhere. In that sense
this shouldn't cause any immediate impact, but Hyper's situation in the
future could change or my analysis could additionally be wrong. Given
the performance benefits here though I'd be tempted to push in favor of
this commit and handle "poll in the background" as necessary in the
future if needed.

Signed-off-by: Alex Crichton <alex@alexcrichton.com>
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
wasi Issues pertaining to WASI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants