You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi,
I'm trying to read a blob file from my disk, like:
#[tokio::main]asyncfnmain() -> std::io::Result<()>{letmut f = File::open("128M.blob").await?.compat();letmut data = Vec::with_capacity(128*1024*1024);AsyncReadExt::read_to_end(&mut f,&mut data).await?;}
In my machine, this code snippet just executed about 2 mins before it returning.
> time ./read_huge_file________________________________________________________Executed in 130.45 secs fish external usr time 129.77 secs 670.00 micros 129.77 secs sys time 1.05 secs 539.00 micros 1.05 secs
investigation
I think this is a little strange, with CPU profiling, I have found that the most of CPU time are used to filling the buffer with 0.
I have read the code of read_to_end_internal, it seems that this function would try to fill the unused part of the vector with zero.
I guess the problem here should be: once the inner reader didn't fully fill the remaining buffer and enter Pending state then, perhaps we must need to fill the remained capacity again in the next poll.
With the perf trace command, we can see that the file implementation of tokio probably reads a 16KB chunk in each read syscall, and would fire a new system call at next poll, hence entering the Pending state, (I guess) it would be like:
File::poll() [emitting result from last task] (returns) Ready(16384)
File::poll() [spawn the read task] (returns) Pending
File::poll() [emitting result from last task] (returns) Ready(16384)
File::poll() [spawn the read task] (returns) Pending
...
With the buffer being slowly full-filled, each time we re-polling the ReadToEnd future, we need to fill the remaining part of buffer, perhaps like:
As a result, we have filled O(m * n) bytes, where n is the capacity, m is how many times the inner future returns Pending. Which would probably result in low performance when reading huge files.
my questions
I'm wondering what is the purpose of initializing the remaining?
I guess if the purpose is to avoid to access uninitialized memory, perhaps we can record an initialized index in the ReadToEnd future, and initialize memory from it (instead of from buf.len()) can help to relive this problem?
Any suggestions about that?
The text was updated successfully, but these errors were encountered:
Well, I have noticed about the comment above that function... So I guess this would be a known issue(or just by design)? If we are not going to do something over that, I'm going to close this.
background
Hi,
I'm trying to read a blob file from my disk, like:
In my machine, this code snippet just executed about 2 mins before it returning.
investigation
I think this is a little strange, with CPU profiling, I have found that the most of CPU time are used to filling the buffer with
0
.I have read the code of
read_to_end_internal
, it seems that this function would try to fill the unused part of the vector with zero.futures-rs/futures-util/src/io/read_to_end.rs
Lines 55 to 64 in 8cfc085
I guess the problem here should be: once the inner reader didn't fully fill the remaining buffer and enter
Pending
state then, perhaps we must need to fill the remained capacity again in the nextpoll
.With the
perf trace
command, we can see that thefile
implementation oftokio
probably reads a 16KB chunk in eachread
syscall, and would fire a new system call at next poll, hence entering thePending
state, (I guess) it would be like:With the buffer being slowly full-filled, each time we re-polling the
ReadToEnd
future, we need to fill the remaining part of buffer, perhaps like:As a result, we have filled
O(m * n)
bytes, wheren
is the capacity,m
is how many times the inner future returnsPending
. Which would probably result in low performance when reading huge files.my questions
I'm wondering what is the purpose of initializing the remaining?
I guess if the purpose is to avoid to access uninitialized memory, perhaps we can record an
initialized
index in theReadToEnd
future, and initialize memory from it (instead of frombuf.len()
) can help to relive this problem?Any suggestions about that?
The text was updated successfully, but these errors were encountered: