libuv는 Boost / ASIO와 어떻게 비교됩니까?


239

다음과 같은 측면에 관심이 있습니다.

  • 범위 / 기능
  • 공연
  • 성숙

20
이 질문을 되돌아 가서 좋은 답변을 얻으십시오!
Viet

\ o / .. 통찰력있는 답변을 얻을 수 있기를 바랍니다.
oberstet

답변:


493

범위

Boost.Asio 는 네트워킹에 중점을 둔 C ++ 라이브러리이지만 비동기 I / O 기능이 다른 리소스로 확장되었습니다. 또한 Boost.Asio가 Boost 라이브러리의 일부인 경우 다른 Boost 라이브러리와 중복되지 않도록 범위가 약간 좁아집니다. 예를 들어 Boost.Thread가 이미 스레드 추상화를 제공하므로 Boost.Asio는 스레드 추상화를 제공하지 않습니다 .

반면에 libuvNode.js 의 플랫폼 레이어로 설계된 C 라이브러리입니다 . Windows의 IOCP , macOS의 kqueue 및 Linux의 epoll 에 대한 추상화를 제공합니다 . 또한 스레드, 스레드 풀 및 스레드 간 통신과 같은 추상화 및 기능을 포함하여 범위가 약간 증가한 것처럼 보입니다.

핵심적으로 각 라이브러리는 이벤트 루프 및 비동기 I / O 기능을 제공합니다. 타이머, 소켓 및 비동기 작업과 같은 일부 기본 기능에 대해서는 중복됩니다. libuv는 더 넓은 범위를 가지고 있으며 스레드 및 동기화 추상화, 동기 및 비동기 파일 시스템 작업, 프로세스 관리 등과 같은 추가 기능을 제공합니다. 반대로 Boost.Asio의 원래 네트워킹 포커스 표면은 풍부한 네트워크 관련 세트를 제공하므로 ICMP, SSL, 동기식 차단 및 비 차단 작업과 같은 기능 및 줄 바꿈이 수신 될 때까지 스트림에서 읽는 것을 포함하여 일반적인 작업에 대한 상위 수준 작업.


기능 목록

다음은 몇 가지 주요 기능에 대한 간단한 비교입니다. Boost.Asio를 사용하는 개발자는 종종 다른 Boost 라이브러리를 사용할 수 있으므로 추가 Boost 라이브러리가 직접 제공되거나 구현하기가 쉽지 않은 경우 추가 Boost 라이브러리를 고려하기로 결정했습니다.

                         libuv 부스트
이벤트 루프 : 예 Asio
스레드 풀 : 예 Asio + 스레드
스레딩 :              
  스레드 : 예 스레드
  동기화 : 예 스레드
파일 시스템 작업 :
  동기식 : 예 FileSystem
  비동기 : 예 Asio + 파일 시스템
타이머 : 예 Asio
분산 형 / 수집 I / O [1] : 아시오 없음
네트워킹 :
  ICMP : 아시오 없음
  DNS 확인 : 비동기 전용 Asio
  SSL : 아시오 없음
  TCP : 비동기 전용 Asio
  UDP : 비동기 전용 Asio
신호:
  처리 : 예 Asio
  발송 : 예 아니요
IPC :
  유닉스 도메인 소켓 : 예
  Windows 명명 된 파이프 : 예 Asio
공정 관리:
  분리 : 예 프로세스
  I / O 파이프 : 예 프로세스
  산란 : 예 프로세스
시스템 검색어 :
  CPU : 예 아니요
  네트워크 인터페이스 : 예 아니요
직렬 포트 : 아니요 예
TTY : 예 아니요
공유 라이브러리 로딩 : 예 확장 [2]

1. 분산 형 / I / O를 수집합니다 .

2. Boost.Extension 은 Boost에 대한 검토를 위해 제출되지 않았습니다. 여기 에 언급 된 바와 같이 저자는 완성 된 것으로 간주합니다.

이벤트 루프

libuv와 Boost.Asio는 모두 이벤트 루프를 제공하지만 둘 사이에는 약간의 차이점이 있습니다.

  • libuv는 여러 이벤트 루프를 지원하지만 여러 스레드에서 동일한 루프를 실행하는 것은 지원하지 않습니다. 따라서 다른 구성 요소가 기본 루프를 실행 중일 수 있으므로 uv_default_loop()새 루프 ( uv_loop_new())를 작성하지 않고 기본 루프 ( )를 사용할 때주의를 기울여야합니다 .
  • Boost.Asio에는 기본 루프 개념이 없습니다. 모두 io_service여러 스레드를 실행할 수있는 자체 루프입니다. 이 Boost.Asio 는 일부 성능을 희생하면서 내부 잠금 을 수행 합니다 . Boost.Asio의 개정 이력 은 잠금을 최소화하기 위해 몇 가지 성능이 개선되었음을 나타냅니다.

스레드 풀

  • libuv는를 통해 스레드 풀을 제공합니다 uv_queue_work. 스레드 풀 크기는 환경 변수를 통해 구성 할 수 있습니다 UV_THREADPOOL_SIZE. 작업은 이벤트 루프 외부와 스레드 풀 내에서 실행됩니다. 작업이 완료되면 완료 핸들러가 이벤트 루프 내에서 실행되도록 큐에 대기됩니다.
  • Boost.Asio는 스레드 풀을 제공하지 않지만 여러 스레드가 호출 될 수 있도록 io_service하여 하나의 기능을 쉽게 수행 할 수 있습니다 . 에서 볼 수 있듯이 이것은 사용자 스레드 관리와 행동의 책임을 배치 예.io_servicerun

스레딩 및 동기화

  • libuv는 스레드 및 동기화 유형에 대한 추상화를 제공합니다.
  • Boost.Thread 는 스레드 및 동기화 유형을 제공합니다. 이러한 유형 중 다수는 C ++ 11 표준을 따르지만 일부 확장도 제공합니다. 여러 스레드가 단일 이벤트 루프를 실행할 수 있도록하는 Boost.Asio의 결과로, 명시 적 잠금 메커니즘을 사용하지 않고 이벤트 핸들러의 순차적 호출을 작성하기위한 수단으로 스트랜드 를 제공합니다 .

파일 시스템 작업

  • libuv는 많은 파일 시스템 작업에 대한 추상화를 제공합니다. 작업 당 하나의 기능이 있으며 각 작업은 동기식 차단 또는 비동기식 일 수 있습니다. 콜백이 제공되면 내부 스레드 풀 내에서 작업이 비동기 적으로 실행됩니다. 콜백이 제공되지 않으면 호출은 동기식 차단입니다.
  • Boost.Filesystem 은 많은 파일 시스템 작업에 대한 동기식 차단 호출을 제공합니다. 이들은 Boost.Asio 및 스레드 풀과 결합하여 비동기 파일 시스템 조작을 작성할 수 있습니다.

네트워킹

  • libuv는 UDP 및 TCP 소켓과 DNS 확인에 대한 비동기 작업을 지원합니다. 응용 프로그램 개발자는 기본 파일 설명자가 비 차단으로 설정되어 있음을 알고 있어야합니다. 따라서 기본 동기 작업은 반환 값을 확인하고 or에 대한 errno 를 확인해야합니다 .EAGAINEWOULDBLOCK
  • Boost.Asio는 네트워킹 지원이 조금 더 풍부합니다. 또한 libuv의 네트워킹이 제공하는 많은 기능인 Boost.Asio는 SSL 및 ICMP 소켓을 지원합니다. 또한 Boost.Asio는 비동기 작업 외에도 동기식 차단 및 동기식 비 차단 작업을 제공합니다. 설정된 바이트 수를 읽거나 지정된 구분 문자를 읽을 때까지 일반적인 상위 수준 작업을 제공하는 수많은 독립형 기능이 있습니다.

신호

  • libuv는 유형과 연산으로 추상화 kill및 신호 처리 기능을 제공합니다 .uv_signal_tuv_signal_*
  • Boost.Asio는에 추상화를 provde하지 않습니다 kill, 그러나 그것은 signal_set신호 처리를 제공합니다.

IPC


API 차이

API 만 언어에 따라 다르지만 다음과 같은 몇 가지 주요 차이점이 있습니다.

조작 및 핸들러 연관

Boost.Asio에는 작업과 처리기간에 일대일 매핑이 있습니다. 예를 들어, 각 async_write작업은 WriteHandler를 한 번 호출합니다 . 이것은 많은 libuv 작업 및 처리기에 적용됩니다. 그러나 libuv uv_async_send는 다 대일 매핑을 지원합니다. 여러 번의 uv_async_send호출로 인해 uv_async_cb 가 한 번 호출 될 수 있습니다 .

콜 체인과 감시자 루프

스트림 / UDP에서 읽기, 신호 처리 또는 타이머 대기와 같은 작업을 처리 할 때 Boost.Asio의 비동기식 호출 체인은 좀 더 명확합니다. libuv를 사용하면 특정 이벤트에 대한 관심을 지정하기 위해 감시자가 작성됩니다. 그런 다음 콜백이 제공되는 감시자에 대해 루프가 시작됩니다. 관심 이벤트가 수신되면 콜백이 호출됩니다. 반면, Boost.Asio는 응용 프로그램이 이벤트 처리에 관심이있을 때마다 작업을 발행해야합니다.

이러한 차이점을 설명하기 위해 다음은 Boost.Asio가있는 비동기 읽기 루프입니다. 여기서 async_receive호출이 여러 번 발행됩니다.

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 );   --'
}    

그리고 여기 libuv와 동일한 예가 있습니다. 여기 handle_read에서 감시자는 소켓에 데이터가 있음을 관찰 할 때마다 호출됩니다.

uv_read_start( socket, alloc_buffer, handle_read ); --.
                                                      |
    .-------------------------------------------------'
    |
    V
void handle_read( ... )
{
  fprintf( stdout, "got data\n" );
}

메모리 할당

Boost.Asio의 비동기 호출 체인과 libuv의 감시자 때문에 메모리 할당이 종종 다른 시간에 발생합니다. 감시자는 libuv는 처리해야 할 메모리가 필요한 이벤트를 수신 할 때까지 할당을 연기합니다. 할당은 사용자 콜백을 통해 이루어지며 libuv 내부에서 호출되며 응용 프로그램의 할당 취소 책임을 연기합니다. 반면, Boost.Asio 작업의 많은 경우 bufferfor 와 같은 비동기 작업을 수행하기 전에 메모리를 할당해야 합니다 async_read. Boost.Asio는 null_buffers이벤트를 수신하는 데 사용할 수있는을 제공 하여 메모리가 필요할 때까지 응용 프로그램이 메모리 할당을 연기 할 수 있도록합니다.

이 메모리 할당 차이는 bind->listen->accept루프 내에서도 나타납니다 . libuv를 uv_listen사용하면 연결을 수락 할 준비가되면 사용자 콜백을 호출하는 이벤트 루프를 만듭니다. 이를 통해 응용 프로그램은 연결을 시도 할 때까지 클라이언트 할당을 연기 할 수 있습니다. 반면에 Boost.Asio는의 listen상태 만 변경합니다 acceptor. async_accept연결 이벤트를 수신하고, 동료를 필요가 호출되기 전에 할당 할 수 있습니다.


공연

불행히도 libuv와 Boost.Asio를 비교할 구체적인 벤치 마크 번호는 없습니다. 그러나 실시간 및 거의 실시간 응용 프로그램에서 라이브러리를 사용하여 비슷한 성능을 관찰했습니다. 어려운 숫자가 필요한 경우 libuv의 벤치 마크 테스트 가 시작점이 될 수 있습니다.

또한 실제 병목 현상을 식별하기 위해 프로파일 링을 수행해야하지만 메모리 할당에주의하십시오. libuv의 경우 메모리 할당 전략은 기본적으로 할당 자 콜백으로 제한됩니다. 반면 Boost.Asio의 API는 할당 자 콜백을 허용하지 않고 대신 할당 전략을 애플리케이션에 푸시합니다. 그러나 Boost.Asio의 핸들러 / 콜백은 복사, 할당 및 할당 해제 될 수 있습니다. Boost.Asio는 애플리케이션이 핸들러에 대한 메모리 할당 전략을 구현하기 위해 사용자 정의 메모리 할당 기능 을 제공 할 수 있도록합니다 .


성숙

부스트. 아시오

Asio의 개발은 2004 년 10 월 이상으로 거슬러 올라가며, 20 일 동료 검토를 거친 후 2006 년 3 월 22 일 부스트 1.35에 채택되었습니다. 또한 TR2네트워킹 라이브러리 제안을 위한 참조 구현 및 API 역할을했습니다 . Boost.Asio는 유용성이 사용자마다 다르지만 상당히 많은 양의 문서 를 가지고 있습니다.

API는 또한 상당히 일관된 느낌을 가지고 있습니다. 또한 비동기 작업은 작업 이름에 명시 적입니다. 예를 들어, accept동기식 차단이며 async_accept비동기식입니다. API는 일반적인 I / O 작업에 대한 무료 기능 (예 : a \r\n을 읽을 때까지 스트림에서 읽는 기능)을 제공합니다 . ip::address_v4::any()의 "모든 인터페이스"주소를 나타내는 것과 같은 일부 네트워크 특정 정보를 숨기도록주의를 기울 였습니다 0.0.0.0.

마지막으로 Boost 1.47+는 C ++ 11 지원뿐만 아니라 디버깅 할 때 유용 할 수있는 핸들러 추적 기능을 제공 합니다 .

리브

github 그래프를 기반으로 Node.js의 개발 날짜는 FEB-2009 이상으로 , libuv의 개발 날짜는 MAR-2011으로되어 있습니다. uvbook는 libuv 도입을위한 좋은 장소입니다. API 설명서는 여기에 있습니다 .

전반적으로 API는 상당히 일관되고 사용하기 쉽습니다. 혼란의 원인이 될 수있는 예외 uv_tcp_listen는 감시자 루프 를 만드는 것입니다. 이는 일반적으로가 다른 관찰자 다르다 uv_*_startuv_*_stop워처 루프의 수명을 제어하는 기능 쌍. 또한 일부 uv_fs_*연산에는 적절한 양의 인수가 있습니다 (최대 7 개). 콜백 (마지막 인수)이있을 때 동기 및 비동기 동작이 결정되면 동기 동작의 가시성이 줄어들 수 있습니다.

마지막으로 libuv 커밋 히스토리를 간략히 살펴보면 개발자가 매우 활동적이라는 것을 알 수 있습니다.


2
고마워요! 좋은 대답입니다! 나는 더 포괄적 인 것을 생각할 수 없다 :)
Viet

1
답변에 매우 만족합니다. 나는 현상금으로 당신에게 상을 수여합니다 :) SO가 자신에게 가장 적합한 답변을 결정하도록하십시오.
Viet

28
놀라운 답변. 여기에는 높은 수준의 그림뿐만 아니라 구체적이고 중요한 세부적인 차이점 (예 : 스레딩 / 이벤트 루프)이 포함됩니다. 대단히 감사합니다!
oberstet

1
@oberstet : 아뇨. 나는 대부분의 libuv 작업이 일대일이라는 언급으로 답변을 업데이트했습니다. 그러나 libuv는 여러 uv_async_send호출을 누적 하고 단일 콜백으로 모두 처리 할 수 ​​있습니다. 여기에 문서화되어 있습니다 . 또한 모두 감사합니다.
Tanner Sansbury

2
Boost.Asio의 이벤트 루프에 대한 내부 잠금은 성능 관점에서 무섭게 보입니다. 잠금없는 libuv와 비슷한 성능을 어떻게 가질 수 있습니까? 성능 섹션에 경고문을 추가하면 도움이 될 수 있습니다.
zeodtr

46

확인. 두 라이브러리를 모두 사용한 경험이 있으며 일부 내용을 정리할 수 있습니다.

첫째, 개념적 관점에서 볼 때 이러한 라이브러리는 디자인이 상당히 다릅니다. 규모가 다르기 때문에 아키텍처가 다릅니다. Boost.Asio는 TCP / UDP / ICMP 프로토콜, POSIX, SSL 등과 함께 사용하기위한 대규모 네트워킹 라이브러리입니다. Libuv는 주로 Node.js 용 IOCP의 크로스 플랫폼 추상화를위한 계층입니다 . 따라서 libuv는 기능적으로 Boost.Asio의 하위 집합입니다 (일반적인 기능은 TCP / UDP 소켓 스레드, 타이머 만 해당). 이 경우 몇 가지 기준 만 사용하여 이러한 라이브러리를 비교할 수 있습니다.

  1. Node.js와의 통합-Libuv는이를 목표로하기 때문에 상당히 좋습니다 (우리는 완전히 통합하여 클라우드와 같은 모든 측면에서 사용할 수 있습니다 (예 : Windows Azure)). 그러나 Asio는 Node.js 이벤트 큐 구동 환경과 거의 동일한 기능을 구현합니다.
  2. IOCP 성능-두 라이브러리 모두 기본 OS API를 추상화하기 때문에 큰 차이점을 볼 수 없었습니다. 그러나 다른 방식으로 수행합니다. Asio는 템플릿 및 TMP와 같은 C ++ 기능을 많이 사용합니다. Libuv는 네이티브 C 라이브러리입니다. 그럼에도 불구하고 IOCP의 Asio 실현은 매우 효율적입니다. Asio의 UDP 소켓은 충분하지 않으므로 libuv를 사용하는 것이 좋습니다.

    새로운 C ++ 기능과의 통합 : Asio가 더 우수합니다 (Asio 1.51은 C ++ 11 비동기 모델을 광범위하게 사용하고 의미론을 이동하며 가변적 템플릿을 사용합니다). 성숙도와 관련하여 Asio는 문서화가 우수한보다 안정적이고 성숙한 프로젝트입니다 (libuv와 비교할 경우) 헤더 설명), 인터넷을 통한 많은 정보 (비디오 토크, 블로그 : http://www.gamedev.net/blog/950/entry-2249317-a-guide-to-getting-started-with-boostasio?pg = 1 등) 및 심지어 책 (전문가는 아니지만 http://en.highscore.de/cpp/boost/index.html ) Libuv는 단 하나의 온라인 서적을 보유하고 있습니다 ( http://nikhilm.github.com/uvbook/index.html).여러 비디오 대화를 통해 모든 비밀을 알기가 어려울 것입니다 (이 라이브러리에는 많은 비밀이 있습니다). 기능에 대한 자세한 설명은 아래 내 의견을 참조하십시오.

결론적으로, 나는 그것이 당신의 목적, 프로젝트 및 구체적으로 무엇을하고자하는지에 달려 있다고 말해야합니다.


11
중요한 것은 기술과 경험입니다. 쿠바 인의 친절한 인사.
dsign

2
Asio의 문서를 제외한 모든 요점에 동의합니다. 공식 문서는이 훌륭한 도서관에 대한 정의를하지 않습니다. 필자가 매우 유용하다고 생각한 다른 문서와 부스트 대화가 많이 있습니다. 그리고 나는 Asio를위한 책을 보지 못했다. 당신의 대답에 그것을 연결할 수 있습니까? 매우 도움이 될 것입니다.
Vikas

@vikas 예 나는 문서가 열악하고 때로는 모순되지만 동의하지만 libuv와 비교하면 시작하기에 좋습니다. 정보)
Oleksandr Karaberov

"libuv는 기능적으로 Boost.Asio (TCP / UDP / Sockets and Threads)의 부분 집합입니다"라는 의미는 무엇입니까? TOC nikhilm.github.com/uvbook/index.html 에 따르면 libuv는 더 넓은 응용 프로그램을 가지고 있으며 boost :: asio입니다.
Sergei Nikulov

7
@AlexanderKaraberov ASIO가 UDP 관련 문제를 확장 할 수 있습니까?
Bruno Martinez


2

이식성 상태 추가 :이 답변을 게시 할 때 본인의 시도에 따라 :

  • Boost.ASIO는 iOS 및 Android를 공식적으로 지원하지 않습니다. 예를 들어 빌드 시스템은 iOS에서 기본적으로 작동하지 않습니다.
  • libuv는 iOS 및 Android 용으로 쉽게 빌드되며 문서 에서 Android를 공식적으로 지원합니다 . Autotools 기반 프로젝트에 대한 제 자신의 일반적인 iOS 빌드 스크립트는 문제없이 작동합니다.

bazel boost 빌드 규칙을 사용하여 bazel을 사용하여 iOS 및 andriod에 대한 크로스 플랫폼 프레임 워크를 작성하는 것은 매우 쉽습니다.
nnrales
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.