Comments (11)
It's a heuristic to reduce the amount of copying, if data frame content is large. If the IO transport can support vectored writes, h2 will use writev to send both pieces without copying.
from h2.
If the IO transport can support vectored writes, h2 will use writev to send both pieces without copying.
I checked the linux manual (https://linux.die.net/man/2/writev) and it says "the data transfers performed by readv() and writev() are atomic: the data written by writev() is written as a single block that is not intermingled with output from writes in other processes"; however it looks like that writev
over a tcp socket on linux (ubuntu 20.4 for my case) does not really aggregate the 2 pieces together first and then send.
Would you be open to improve the heuristic? My proposal is
- Increase
CHUNK_THRESHOLD
a little bit, to like1024
- When chaining a payload, still copy first
X
bytes to buffer, and chain the rest of the payload; hereX
isCHUNK_THRESHOLD - buf.remaining()
No matter what, the current performance is not ideal, for the scenarios where large amounts of small payload (around 1KB) are being transmitted
from h2.
If you feel comfortable with my proposal or can suggest an alternative, I will be happy to implement it, submit a pull request, etc.
from h2.
writev on a TCP socket will result it the data going together, unless the amount of data is too large for a single segment of course. However, if using TLS on top, some of the transports don't implement the is_write_vectored()
method.
I'm open to improving the throughput, certainly! I think that if vectored writes are supported, the threshold should stay small. But if it's not supported, it could definitely make sense to have up to a certain size buffering.
It'd help if there were some benchmarks that could show the improvement. hyper has some end-to-end benchmarks for different sizes and amounts of requests, that could be a good place to measure (or add a case that can then measure).
from h2.
writev on a TCP socket will result it the data going together, unless the amount of data is too large for a single segment of course. However, if using TLS on top, some of the transports don't implement the is_write_vectored() method.
I didn't find much documents about vectorized write. In my environement, OS is Ubuntu 20.04.3 LTS; 2 packets are written at once, one of 9 bytes, the other of around 1000 bytes; TLS is not used.
It's possible that I have some inproper configs but after some researches, I didn't find what linux settings would control the behavior of writev
over a TCP socket. Also keep in mind that whether TCP_NODELAY
is set also affects the behavior, in my case TCP_NODELAY
is on.
I think that if vectored writes are supported, the threshold should stay small. But if it's not supported, it could definitely make sense to have up to a certain size buffering.
Good suggestion; but it might be easy to tell whether vectored io is support or not. For example, in the implementation of TcpStream
in tokio (https://github.com/tokio-rs/tokio/blob/37bb47c4a2aff8913e536767645772f15650e6cd/tokio/src/net/tcp/stream.rs#L1348-L1350), TcpStream::is_write_vectored()
always returns true no matter what.
It'd help if there were some benchmarks that could show the improvement.
I would certainly make sure to use benchmark to measure perf changes through benchmarks
from h2.
for more information, I tested TcpStream::write_vectored()
from tokio
in my test environment and the write here is indeed atomic (all payload is concatenated); so looks like when using tonic
for grpc, the observed extra tcp segment might be due to some other stuff, I will keep it posted
from h2.
I think I find (or get closer to) the root cause for my issue: tonic
does not really implement the vectored io part for its BoxIo
, which is a wrapper of the underlying TCP stream (https://github.com/hyperium/tonic/blob/2325e3293b8a54f3412a8c9a5fcac064fa82db56/tonic/src/transport/service/io.rs#L52-L52)
So looks like I can help with these stuff
- Fix the vectored IO part on tonic
- Fix
Tcp::is_write_vectored()
in tokio - Improve the heuristics here when vectored io is not supported
Let me know what you think. :)
from h2.
I think 1 and 3 would be great. Didn't you say you've already tested that 2 works?
from h2.
For 2, looks like always return true (https://github.com/tokio-rs/tokio/blob/37bb47c4a2aff8913e536767645772f15650e6cd/tokio/src/net/tcp/stream.rs#L1348-L1350), but correct implementation shall depend on the underlying TcpStream.
Without 2, even if 1 and 3 are fixed, it won't help with the non-vectored case since h2
will assume the vectored IO is on, and uses default implementation of write_vectored()
, which actually sends each buffer one by one
from h2.
I believe it always returns true because it has a specialized poll_write_vectored
, which uses writev
on the socket.
1 and 3 seem higher priority.
from h2.
Cool, I will do 1 and 3 first.
However, for 2, I looked through the codebase again, and looks like its poll_write_vectored
is implemented as (https://github.com/tokio-rs/tokio/blob/37bb47c4a2aff8913e536767645772f15650e6cd/tokio/src/io/poll_evented.rs#L218-L230)
#[cfg(any(feature = "net", feature = "process"))]
pub(crate) fn poll_write_vectored<'a>(
&'a self,
cx: &mut Context<'_>,
bufs: &[io::IoSlice<'_>],
) -> Poll<io::Result<usize>>
where
&'a E: io::Write + 'a,
{
use std::io::Write;
self.registration.poll_write_io(cx, || self.io.as_ref().unwrap().write_vectored(bufs))
}
here self.io
is actually of type mio::net::TcpStream
, whose write_vectored
implementation is still based on the TcpStream
from ruststd
.
By the end of the day, if an OS / device does not support vector IO, I feel tokio::TcpStream
cannot do much to enable vectored write without manipulation of a bulk of memory. So I feel the is_write_vectored
still needs to be changed in tokio
Let me know if I misunderstood any stuff, thanks! ;)
from h2.
Related Issues (20)
- Panicking following 0.3.17 HOT 1
- Unable to send response. HOT 3
- assertion failed: self.num_remote_reset_streams > 0 HOT 1
- How to set frame priority / Weight ? HOT 4
- Request processing always times out, HOT 1
- Handling of RFC7540 8.1.2.5 HOT 5
- Panic due to the max headers capacity HOT 1
- `h2spec 2.6.0` tests are failling against `h2` HOT 3
- Settings frames are not applied correctly HOT 12
- Make tracing an optional feature
- Modifying the `akamai` example to send to `www.google.com` and adding a `host` header and errors HOT 2
- `max_send_buffer_size` documentation states default is 400 MB. It is 400 KB. HOT 2
- Remove tokio I/O traits from dependencies HOT 4
- http2 error: stream error received: unspecific protocol error detected HOT 4
- custom SETTINGS settings
- Proposal: change the default value of `initial_max_send_streams` to 100 HOT 7
- Documentation: How to handle GOAWAY HOT 2
- Respond with an HTTP 4xx than only a `RST_STREAM` to malformed requests HOT 2
- Default server configuration prevents the use of server pushes HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from h2.