2017-04-30 6 views
0

私はlibuvの性能を評価しようとしています。なぜなら、100,000のTCPソケットを管理でき、毎秒10,000の新しいTCPセッションを生成できるという約束のためです。libuvは複数の接続を確立するのが遅いですか?

libuvのパフォーマンスを検証するための要点に基づいて、次のコードスニペットを作成しました。それは、サーバーに対して実行する場合しかし、それはpcap capture

  • TCPハンドシェイクが次々と行われたwiresharkのに応じて、驚くほど遅いですが、私はTCPのSYNを期待していたことは結局送信された並列
  • TCPデータで送信されますセッションが確立されました。私は、TCPハンドシェイクが完了するとすぐにTCPデータが送信されることを期待していました。

このテストは、Ubuntu 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リポジトリには多くの良い例があります。 "test"サブディレクトリを確認してください。

関連する問題