¿Cómo se compara libuv con Boost / ASIO?
Me interesarían aspectos como:
- alcance / características
- rendimiento
- vencimiento
3 answers
Ámbito de aplicación
Boost.Asio es una biblioteca de C++ que comenzó con un enfoque en redes, pero sus capacidades de E/S asincrónicas se han extendido a otros recursos. Además, con Boost.Asio es parte de las bibliotecas de Boost, su alcance se reduce ligeramente para evitar la duplicación con otras bibliotecas de Boost. Por ejemplo, Boost.Asio no proporcionará una abstracción de hilo, como Boost.Thread ya proporciona uno.
Por otro lado, libuv es una biblioteca C diseñada para ser la capa de plataforma para el nodo .js . Proporciona una abstracción a IOCP para Windows y libev en sistemas Unix. Aunque hay esfuerzos para eliminar libev como se indica en este problema. Además, parece que su alcance ha aumentado ligeramente para incluir abstracciones y funcionalidad, como hilos, threadpools y comunicación entre hilos.
En su núcleo, cada biblioteca proporciona un bucle de eventos y capacidades de E/S asincrónicas. Tienen superposición para algunas de las características básicas, como temporizadores, sockets y operaciones asíncronas. libuv tiene un alcance más amplio y proporciona funcionalidad adicional, como abstracciones de subprocesos y sincronización, operaciones de sistemas de archivos síncronos y asíncronos, gestión de procesos, etc. En contraste, Boost.Las superficies de enfoque de red originales de Asio, ya que proporciona un conjunto más rico de capacidades relacionadas con la red, como ICMP, SSL, bloqueo síncrono y operaciones sin bloqueo y operaciones de nivel superior para tareas comunes, incluida la lectura de una transmisión hasta que se reciba una nueva línea.
Lista de características
Aquí está la breve comparación lado a lado sobre algunas de las características principales. Desde desarrolladores usando Boost.Asio a menudo tiene otras bibliotecas Boost disponibles, he optado por considerar bibliotecas Boost adicionales si se proporcionan directamente o son triviales de implementar.
libuv Boost Event Loop: yes Asio Threadpool: yes Asio + Threads Threading: Threads: yes Threads Synchronization: yes Threads File System Operations: Synchronous: yes FileSystem Asynchronous: yes Asio + Filesystem Timers: yes Asio Scatter/Gather I/O[1]: no Asio Networking: ICMP: no Asio DNS Resolution: async-only Asio SSL: no Asio TCP: async-only Asio UDP: async-only Asio Signal: Handling: yes Asio Sending: yes no IPC: UNIX Domain Sockets: yes Asio Windows Named Pipe: yes Asio Process Management: Detaching: yes Process I/O Pipe: yes Process Spawning: yes Process System Queries: CPU: yes no Network Interface: yes no Serial Ports: no yes TTY: yes no Shared Library Loading: yes Extension[2]
2. Aumentar.La extensión nunca fue enviada para su revisión a Boost. Como se señala aquí, el autor lo considera completo.
Bucle de eventos
Mientras tanto libuv y Boost.Asio proporcionar bucles de eventos, hay algunas diferencias sutiles entre los dos:
- Si bien libuv admite varios bucles de eventos, no admite la ejecución del mismo bucle desde varios subprocesos. Por esta razón, hay que tener cuidado cuando usando el bucle predeterminado (
uv_default_loop()
), en lugar de crear un nuevo bucle (uv_loop_new()
), ya que otro componente puede estar ejecutando el bucle predeterminado. - Aumentar.Asio no tiene la noción de un bucle predeterminado; todos
io_service
son sus propios bucles que permiten ejecutar múltiples subprocesos. Para apoyar este Impulso.Asio realizabloqueo interno a costa de algunosrendimiento . Impulsar.La revisión de Asio historia indica que ha habido varias mejoras de rendimiento para minimizar el bloqueo.
Threadpool
- libuv proporciona un threadpool a través de
uv_queue_work
. El tamaño de threadpool es un detalle de implementación y no parece configurable a través de la API. El trabajo se ejecutará fuera del bucle de eventos y dentro del threadpool. Una vez que se complete el trabajo, el controlador de finalización se pondrá en cola para ejecutarse dentro del bucle de eventos. - Mientras Boost.Asio no proporciona un threadpool, el
io_service
puede funcionar fácilmente como uno como resultado deio_service
permitiendo que múltiples hilos invoquenrun
. Esto coloca la responsabilidad de la gestión de subprocesos y el comportamiento al usuario, como se puede ver en este ejemplo.
Enhebrado y sincronización
- libuv proporciona una abstracción a los subprocesos y tipos de sincronización.
-
Aumentar.Thread proporciona un hilo y tipos de sincronización. Muchos de estos tipos siguen de cerca el estándar C++11, pero también proporcionan algunas extensiones. Como resultado de Boost.Asio permite que múltiples hilos ejecuten un solo bucle de eventos, proporciona
strands
como un medio para crear una invocación secuencial de controladores de eventos sin usar mecanismos de bloqueo explícitos.
Operaciones del Sistema de Archivos
- libuv proporciona una abstracción a muchas operaciones del sistema de archivos. Hay una función por operación, y cada operación puede ser de bloqueo síncrono o asíncrono. Si se proporciona una devolución de llamada, entonces la operación será ejecutado de forma asíncrona dentro de un threadpool interno. Si no se proporciona una devolución de llamada, entonces la llamada será un bloqueo síncrono.
- Aumentar.Filesystem proporciona llamadas de bloqueo síncronas para muchas operaciones del sistema de archivos. Estos se pueden combinar con Boost.Asio y un threadpool para crear operaciones asíncronas del sistema de archivos.
Redes
- libuv soporta operaciones asíncronas en sockets UDP y TCP, así como resolución DNS. Aplicación los desarrolladores deben tener en cuenta que los descriptores de archivo subyacentes están configurados en no bloqueo. Por lo tanto, las operaciones síncronas nativas deben verificar los valores devueltos y errno para
EAGAIN
oEWOULDBLOCK
. - Aumentar.Asio es un poco más rico en su soporte de redes. Además, muchas de las características que ofrece la red de libuv, Boost.Asio soporta sockets SSL e ICMP. Además, Boost.Asio proporciona operaciones de bloqueo síncrono y sin bloqueo síncrono, además de su operaciones asíncronas. Hay numerosas funciones independientes que proporcionan operaciones comunes de nivel superior, como leer una cantidad determinada de bytes, o hasta que se lea un carácter delimitador especificado.
Señal
- libuv proporciona una abstracción
kill
y manejo de señales con su tipouv_signal_t
y operacionesuv_signal_*
. En este momento, solo el bucle de eventos predeterminado admite señales. - Aumentar.Asio no proporciona una abstracción a
kill
, pero susignal_set_service
proporciona manejo de señales.
IPC
- libuv abstracts Unix Domain Sockets and Windows Named Pipes through a single
uv_pipe_t
type. - Aumentar.Asio separa a los dos en locales::stream_protocol::socket/local::datagram_protocol::socket y
windows::stream_handle
.
Diferencias de API
Si bien las API son diferentes solo en función del idioma, aquí hay algunas claves diferencias:
Operación y Asociación del Manejador
Dentro de Boost.Asio, hay un mapeo uno a uno entre una operación y un manejador. Por ejemplo, cada async_write
la operación invocará el WriteHandler una vez. Esto es cierto para muchas de las operaciones y manejadores de libuv. Sin embargo, el uv_async_send
de libuv soporta una asignación de muchos a uno. Múltiples llamadas uv_async_send
pueden resultar en que el uv_async_cb sea llamado una vez.
Call Chains vs. Watcher Bucles
Cuando se trata de tareas, como leer desde un flujo/UDP, manejar señales o esperar temporizadores, aumente.Las cadenas de llamadas asíncronas de Asio son un poco más explícitas. Con libuv, se crea un observador para designar intereses en un evento en particular. Luego se inicia un bucle para el observador, donde se proporciona una devolución de llamada. Al recibir el evento de intereses, se invocará la devolución de llamada. Por otro lado, Boost.Asio requiere que se emita una operación cada vez que se interesados en manejar el evento.
Para ayudar a ilustrar esta diferencia, aquí hay un bucle de lectura asíncrono con Boost.Asio, donde la async_receive
llamada se emitirá varias veces:
void start()
{
socket.async_receive( buffer, handle_read ); ----.
} |
.----------------------------------------------'
| .---------------------------------------.
V V |
void handle_read( ... ) |
{ |
std::cout << "got data" << std::endl; |
socket.async_receive( buffer, handle_read ); --'
}
Y aquí está el mismo ejemplo con libuv, donde handle_read
se invoca cada vez que el observador observa que el socket tiene datos:
uv_read_start( socket, alloc_buffer, handle_read ); --.
|
.-------------------------------------------------'
|
V
void handle_read( ... )
{
fprintf( stdout, "got data\n" );
}
Asignación de memoria
Como resultado de las cadenas de llamadas asíncronas en Boost.Asio y los observadores en libuv, la asignación de memoria a menudo ocurre en tiempos diferentes. Con watchers, libuv aplaza la asignación hasta después de recibir un evento que requiere memoria para manejar. La asignación se realiza a través de una devolución de llamada de usuario, invocada internamente a libuv, y aplaza la responsabilidad de desasignación de la aplicación. Por otro lado, muchos de los Boost.Las operaciones Asio requieren que se asigne la memoria antes de emitir la operación asíncrona, como el caso de buffer
para async_read
. Impulsar.Asio proporciona null_buffers
, que se puede utilizar para escuchar un evento, lo que permite a las aplicaciones aplazar la asignación de memoria hasta que se necesite memoria.
Esta diferencia de asignación de memoria también se presenta dentro del bucle bind->listen->accept
. Con libuv, uv_listen
crea un bucle de eventos que invocará la devolución de llamada del usuario cuando una conexión esté lista para ser aceptada. Esto permite que la aplicación aplace la asignación del cliente hasta que se intente una conexión. Por otro lado, Boost.Asio's listen
solo cambia el estado de la acceptor
. Las async_accept
escucha el evento de conexión y requiere que el par sea asignado antes de ser invocado.
Rendimiento
Desafortunadamente, no tengo ningún número de referencia concreto para comparar libuv y Boost.Asio. Sin embargo, he observado un rendimiento similar utilizando las bibliotecas en aplicaciones en tiempo real y casi en tiempo real. Si se desean números duros, la prueba de referencia de libuv puede servir como punto de partida punto.
Además, mientras que el perfilado debe hacerse para identificar los cuellos de botella reales, tenga en cuenta las asignaciones de memoria. Para libuv, la estrategia de asignación de memoria se limita principalmente a la devolución de llamada del asignador. Por otro lado, Boost.La API de Asio no permite una devolución de llamada del asignador, y en su lugar envía la estrategia de asignación a la aplicación. Sin embargo, los handlers/callbacks en Boost.Asio puede ser copiado, asignado y desasignado. Impulsar.Asio permite que las aplicaciones proporcionen custom memory allocation funciona para implementar una estrategia de asignación de memoria para los controladores.
Vencimiento
Aumentar.Asio
El desarrollo de Asio se remonta al menos a OCTUBRE de 2004, y fue aceptado en Boost 1.35 el 22 de marzo de 2006 después de someterse a una revisión por pares de 20 días. También sirvió como la implementación de referencia y API para Propuesta de Biblioteca de redes para TR2. Impulsar.Asio tiene una buena cantidad de documentación, aunque su utilidad varía de usuario a usuario.
La API también tiene una sensación bastante consistente. Además, las operaciones asíncronas son explícitas en el nombre de la operación. Por ejemplo, accept
es bloqueo síncrono y async_accept
es asíncrono. La API proporciona funciones gratuitas para tareas comunes de E / S, por ejemplo, leer desde un flujo hasta que se lee un \r\n
. También se ha prestado atención a ocultar algunos detalles específicos de la red, como el ip::address_v4::any()
que representa el " todas las interfaces" dirección de 0.0.0.0
.
Finalmente, Boost 1.47+ proporciona seguimiento del controlador, que puede resultar útil al depurar, así como soporte para C++11.
Libuv
Basado en sus gráficos de github, Node.el desarrollo de js se remonta al menos a FEB-2009, y el desarrollo de libuv se remonta a MAR-2011. El uvbook es un gran lugar para una introducción a libuv. La API está documentada en forma de un encabezado detallado, pero podría todavía utilizar contribuciones en algunas áreas.
En general, la API es bastante consistente y fácil de usar. Una anomalía que puede ser una fuente de confusión es que uv_tcp_listen
crea un bucle de vigilante. Esto es diferente a otros observadores que generalmente tienen un par de funciones uv_*_start
y uv_*_stop
para controlar la vida del bucle watcher. Además, algunas de las operaciones uv_fs_*
tienen una cantidad decente de argumentos (hasta 7). Con el comportamiento síncrono y asíncrono se determina en la presencia de un callback (el último argumento), la visibilidad del comportamiento síncrono puede ser disminuida.
Finalmente, un rápido vistazo al historial de confirmaciones de libuv muestra que los desarrolladores están muy activos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-06 07:41:23
Ok. Tengo cierta experiencia en el uso de ambas bibliotecas y puedo aclarar algunas cosas.
Primero, desde un punto de vista conceptual, estas bibliotecas son bastante diferentes en diseño. Tienen arquitecturas diferentes, porque son de diferente escala. Impulsar.Asio es una gran biblioteca de redes destinada a ser utilizada con protocolos TCP/UDP/ICMP, POSIX, SSL, etc. Libuv es solo una capa para la abstracción multiplataforma de IOCP para Nodo.js, predominantemente. Así que libuv es funcionalmente un subconjunto de Impulsar.Asio (características comunes solo TCP/UDP Sockets threads, temporizadores). Siendo ese el caso, podemos comparar estas bibliotecas usando solo unos pocos criterios:
- Integración con Node.js-Libuv es considerablemente mejor porque está dirigido a esto (podemos integrarlo completamente y usarlo en todos los aspectos, por ejemplo, en la nube, por ejemplo, windows azure). Pero Asio también implementa casi la misma funcionalidad que en Node.js event queue driven environment.
- Rendimiento del IOCP-No pude ver muy bien diferencias, porque ambas bibliotecas abstraen la API del sistema operativo subyacente. Pero lo hacen de una manera diferente: Asio usa en gran medida características de C++ como plantillas y, a veces, TMP. Libuv es una biblioteca-C nativa. Pero sin embargo la realización Asio del IOCP es muy eficiente. Los sockets UDP en Asio no son lo suficientemente buenos, es mejor usar libuv para ellos.
Integración con nuevas características de C++: Asio es mejor (Asio 1.51 utiliza ampliamente el modelo asíncrono C++11, semántica de movimiento, plantillas variádicas). madurez, Asio es un proyecto más estable y maduro con buena documentación (si se compara con la descripción de los encabezados de libuv), mucha información a través de Internet (charlas de video, blogs: http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg=1, etc.) e incluso libros (no para profesionales, pero sin embargo: http://en.highscore.de/cpp/boost/index.html ). Libuv tiene solo un libro en línea (pero también es bueno) http://nikhilm.github.com/uvbook/index.html y varias charlas en video, por lo que será difícil conocer todos los secretos (esta biblioteca tiene muchos de ellos). Para una discusión más específica de las funciones ver mis comentarios a continuación.
Como conclusión, debo decir que todo depende de sus propósitos, su proyecto y lo que concretamente pretende hacer.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-02 20:51:32
Una gran diferencia es que el autor de Asio (Christopher Kohlhoff) está preparando su biblioteca para su inclusión en la Biblioteca Estándar de C++, ver http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2175.pdf y http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4370.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-25 14:36:57