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
{{ message }}
This repository was archived by the owner on Nov 23, 2017. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 23, 2017. It is now read-only.
Serious performance loss (10 times) when NOT using .drain() #338
Very strange, .drain() should slow down program since adds pause. But in reality, it greatly speedup program. Maybe because pipe size is less than 1 MB and equal 65536 bytes?
I can repro on OSX too. Interestingly, if I increase the read() buffer to 1MB I still get the data fed in 64k blocks.
I think there's something quadratic going on in _UnixWritePipeTransport._write_ready(); if I double the data written the time it takes without the drain() call quadruples; with the drain that hardly makes a dent.
I have to stop analyzing this further, but it looks like _write_ready() repeatedly tries to write the entire buffer (which, without the drain() call, starts off at 30 MB). But only 64 KB gets written, and the rest gets pushed back into the buffer. This means a lot of copying of the data happens. Someone should probably try to avoid this behavior.
But in the mean time, this is exactly why drain() was invented, so use it. :-)
UNIX pipes are limited with 64K of kernel buffers by default, so no one can write at once more than 64K to a pipe.
We should use os.writev() instead of gathering buffers in one big chunk. This is why this sycall was invented. Do you approve that?
drain() was not invented to speedup operations, it was invented to prevent buffer bloat...But in my task buffer bloating is not a problem, so I should acheive good speed even without drain()
Activity
socketpair commentedon May 2, 2016
Very strange,
.drain()should slow down program since adds pause. But in reality, it greatly speedup program. Maybe because pipe size is less than 1 MB and equal 65536 bytes?gvanrossum commentedon May 2, 2016
I can repro on OSX too. Interestingly, if I increase the
read()buffer to 1MB I still get the data fed in 64k blocks.I think there's something quadratic going on in
_UnixWritePipeTransport._write_ready(); if I double the data written the time it takes without thedrain()call quadruples; with the drain that hardly makes a dent.I have to stop analyzing this further, but it looks like
_write_ready()repeatedly tries to write the entire buffer (which, without thedrain()call, starts off at 30 MB). But only 64 KB gets written, and the rest gets pushed back into the buffer. This means a lot of copying of the data happens. Someone should probably try to avoid this behavior.But in the mean time, this is exactly why
drain()was invented, so use it. :-)socketpair commentedon May 2, 2016
UNIX pipes are limited with 64K of kernel buffers by default, so no one can write at once more than 64K to a pipe.
We should use
os.writev()instead of gathering buffers in one big chunk. This is why this sycall was invented. Do you approve that?drain()was not invented to speedup operations, it was invented to prevent buffer bloat...But in my task buffer bloating is not a problem, so I should acheive good speed even withoutdrain()gvanrossum commentedon May 2, 2016
socketpair commentedon May 2, 2016
I have created PR. But cannot easily patch tests....
Example:
socketpair commentedon May 2, 2016
Please help me, point how I can write test
m_writev.assert_called_with(5, ????)gvanrossum commentedon May 2, 2016
1st1 commentedon Sep 15, 2016
I think this issue can be closed since we've merged #385. Please open a new one specifically to discuss vectorized writes in 3.7.