2017-04-30 6 views
0

libuv는 100,000 개의 TCP 소켓을 관리 할 수 ​​있고 1 초당 10,000 개의 새로운 TCP 세션을 생성 할 수 있기 때문에 libuv의 성능을 평가하려고합니다.여러 연결을 설정하는 데 libuv가 느린가요?

libuv의 성능을 검증하기위한 요점을 토대로 다음 코드 스 니펫을 작성했습니다. 이 서버에 대해 실행 그러나, 그것은 pcap capture

  • TCP 핸드 쉐이크가 잇달아 수행했다 와이어 샤크에 따라 놀라 울 정도로 느린, 나는 TCP 않은 SYN을 기다리고 있었다 것은 결국 전송 된 병렬
  • 하는 TCP 데이터에서 확인할 수 있습니다 세션이 수립되었습니다. TCP 핸드 셰이크가 완료 되 자마자 TCP 데이터가 전송 될 것으로 예상했습니다.

이 테스트는 우분투 14.04 (64 비트 코어 i7 cpu)에서 실행되었습니다.

libuv 또는이 코드 스 니펫에 문제가 있는지 확실하지 않습니다.

메모리 누수가 있음을 알고 있지만, 평가 만하기 때문에 중요하지 않습니다.

#include <stdio.h> 
#include <stdlib.h> 
#include <uv.h> 

//based on https://gist.githubusercontent.com/snatchev/5255976/ 
//raw/8392c42d719bb775053036e32b21affdf932c1b7/libuv-tcp-client.c 
static void on_close(uv_handle_t* handle); 
static void on_connect(uv_connect_t* req, int status); 
static void on_write(uv_write_t* req, int status); 

static uv_loop_t *loop; 

static uv_buf_t alloc_cb(uv_handle_t* handle, size_t size) { 
    return uv_buf_init(malloc(size), size); 
} 

void on_close(uv_handle_t* handle) 
{ 
    printf("closed."); 
} 

void on_write(uv_write_t* req, int status) 
{ 
    if (status) { 
    uv_err_t err = uv_last_error(loop); 
    fprintf(stderr, "uv_write error: %s\n", uv_strerror(err)); 
     return; 
    } 
    printf("wrote.\n"); 
    free(req); 
    //uv_close((uv_handle_t*)req->handle, on_close); 
} 

void on_read(uv_stream_t* tcp, ssize_t nread, uv_buf_t buf) 
{ 
    printf("on_read. %p\n",tcp); 
    if(nread >= 0) { 
     //printf("read: %s\n", tcp->data); 
     printf("read: %s\n", buf.base); 
    } 
    else { 
     //we got an EOF 
    uv_close((uv_handle_t*)tcp, on_close); 
    } 

    //cargo-culted 
    free(buf.base); 
} 

void write2(uv_stream_t* stream, char *data, int len2) { 
    uv_buf_t buffer[] = { 
     {.base = data, .len = len2} 
    }; 
    uv_write_t *req = malloc(sizeof(uv_write_t)); 
    uv_write(req, stream, buffer, 1, on_write); 
} 

void on_connect(uv_connect_t* connection, int status) 
{ 
    if (status < 0) { 
     printf("failed to connect\n"); return; 
    } 
    printf("connected. %p %d\n",connection, status); 

    uv_stream_t* stream = connection->handle; 
    free(connection); 
    write2(stream, "echo world!", 12); 
    uv_read_start(stream, alloc_cb, on_read); 
} 

void startConn(char *host, int port) { 
    uv_tcp_t *pSock = malloc(sizeof(uv_tcp_t)); 
    uv_tcp_init(loop, pSock); 
    uv_tcp_keepalive(pSock, 1, 60); 

    struct sockaddr_in dest = uv_ip4_addr(host, port); 

    uv_connect_t *pConn = malloc(sizeof(uv_connect_t)); 
    printf("allocated %p\n", pConn); 
    uv_tcp_connect(pConn, pSock, dest, on_connect); 
} 

int main(int argc, char **argv) { 
    loop = uv_default_loop(); 
    int i; 
    for (i=0; i<10; i++) 
     startConn("0.0.0.0", 1234); 

    uv_run(loop, UV_RUN_DEFAULT); 
} 
+0

1. 'printf'없이 시도 했습니까? (IO 액세스 차단으로 인해 동기화 수준이 높아졌습니다)? ... 2. 궁금합니다. libuv가 서버 역할을 할 때도 이런 일이 발생합니까? – Myst

+0

제안에 감사드립니다 @Myst는'printf'가 아무런 효과를 내지 못했다고 설명했습니다. 나는 현재 클라이언트로서 libuv에서 흥미 롭다. 앞으로 서버 측을 시도 할 것이다. – packetie

+0

또 하나의 생각은 덜 안정적인 API라는 것을 알고 있지만,'uv_tcp_connect'를 호출하기 전에'uv_stream_set_blocking (pSock, 0)'을 사용해 보았습니까? – Myst

답변

0

이 예는 libuv 0.1에 대해 컴파일됩니다.

libuv1.x에 대해 컴파일 및 실행 한 후 예상대로 작동합니다. 다음은 gist입니다.

libuv 0.1과 libuv 1.0에는 상당한 차이가 있습니다. 이 버전이 libuv.c의 실제 예제를 찾는 사람들에게 도움이되기를 바랍니다. 그건 그렇고, github에서 libuv repo에 많은 좋은 예가 있습니다. "test"하위 디렉토리를 확인하십시오.