MagicStack / MagicStack/uvloop

Using vectorized IO (scatter/gather)

Abierto
#404 3 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Lenguaje dominante
Cython
Estrellas
11.9k
Forks
616
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

Operations like `writelines` in [the Stream]( https://docs.python.org/3/library/asyncio-stream.html#asyncio.StreamWriter.writelines ) and [the Transport]( https://docs.python.org/3/library/asyncio-protocol.html?highlight=writelines#asyncio.WriteTransport.writelines ) APIs provide library authors the opportunity to send collections of buffers that they would like written, sent, etc. in one go. This can be really handy as it takes only one pass (as opposed to multiple passes) through layers of code to prepare buffers before they go out.

Many OSes supply similar C-level operations like [`writev` on POSIX compatible or similar on Windows]( https://en.wikipedia.org/wiki/Vectored_I/O ) for operating on file descriptors. Similarly [`sendmsg` on Linux and Unix]( https://linux.die.net/man/3/sendmsg ) or [`WSASend` on Windows]( https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasend ) provide implementations for sockets.

Admittedly am not very familiar with `libuv`'s API (so maybe devs here can comment on this), but it appears there are some APIs in `libuv` like [`uv_write`]( http://docs.libuv.org/en/v1.x/stream.html#c.uv_write ) can take multiple buffers, which can [internally redirect]( https://github.com/libuv/libuv/blob/285a5ea819035ff777b8b7c6a367f3f5b55d8809/src/unix/udp.c#L728 ) to [`sendmsg`]( https://github.com/libuv/libuv/blob/285a5ea819035ff777b8b7c6a367f3f5b55d8809/src/unix/udp.c#L448 ) or [`WSASend`]( https://github.com/libuv/libuv/blob/4ddc292774be827a297449e2d5ef4047c85de7ca/src/win/tcp.c#L934 ). This also appears to be true for files with the [`uv_fs_write`]( http://docs.libuv.org/en/v1.x/fs.html#c.uv_fs_write ) API.

AFAICT (and I could be wrong about this) `uvloop`'s `writelines` for Streams calls an internal [`_write` function in a loop]( https://github.com/MagicStack/uvloop/blob/70cafc82ccfc660c52ed2e31d9e36dfb3afe5c9d/uvloop/handles/stream.pyx#L692-L693 ), which could [write one entire buffer (if it is sufficiently large, etc.)]( https://github.com/MagicStack/uvloop/blob/70cafc82ccfc660c52ed2e31d9e36dfb3afe5c9d/uvloop/handles/stream.pyx#L433 ) or at least [queue a write]( https://github.com/MagicStack/uvloop/blob/70cafc82ccfc660c52ed2e31d9e36dfb3afe5c9d/uvloop/handles/stream.pyx#L449 ). Please correct me if I'm misunderstanding anything here.

However given libuv's own propensity to use scatter/gather IO under-the-hood, it might be worth holding off on queuing write operations until all of the buffers in `writelines` are collected and prepped. This would allow one larger send, write, etc. to occur and if it is above the high watermark for any buffer (likely?), no additional buffer prepping would be necessary either.


**Side note:** A separate interesting question would be doing something similar for reading. Not sure there is an API that could leverage this currently (may be wrong about this though). Maybe through pausing and resuming reading one could get close (though likely still leaves something on the table)?

**Note:** There may be similar optimizations possible in [asyncio]( https://bugs.python.org/issue40007 ) ( https://github.com/python/asyncio/pull/339 ) ( https://github.com/python/cpython/pull/19062 )

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza con uvloop/handles/stream.pyx alrededor de las líneas referenciadas de writelines y _write; después, inspecciona las APIs enlazadas de libuv uv_write, uv_fs_write, sendmsg y WSASend. Determina si recopilar los buffers de writelines puede permitir una operación vectorizada y define el alcance resultante y los criterios de finalización.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
python
Área
networking, performance
Tipo de issue
Nueva funcionalidad
Dificultad
5/5
Tiempo estimado
Más de una semana
Estado de actividad
Estancado
Claridad
Necesita aclaración
Aptitud para principiantes
30/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.