【问题标题】:libuv slow in establishing a multiple connections?libuv 建立多个连接的速度很慢?
【发布时间】:2017-04-30 16:08:28
【问题描述】:

我正在尝试评估 libuv 的性能,因为它承诺可以管理 100,000 个 TCP 套接字,并且每秒可以生成 10,000 个新 TCP 会话。

根据 gist 创建了以下代码 sn-p 来验证 libuv 的性能。但是,当它在服务器上运行时,根据wireshark pcap capture 的说法,它出奇地慢

  • TCP 握手接连完成,我希望 TCP SYN 可以并行发送
  • TCP 数据是在所有会话建立后发送的。我原以为 TCP 握手完成后会立即发送 TCP 数据。

此测试在 Ubuntu 14.04(64 位核心 i7 cpu)上运行。

不确定 libuv 或这段代码 sn-p 是否有问题。

我知道这有一些内存泄漏,但这没关系,因为我只是在做评估。

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

【问题讨论】:

  • 1.您是否在没有printf 的情况下尝试过此操作(由于阻塞 IO 访问,它们会引发一定程度的同步)? ... 2. 我想知道,libuv 充当服务器时也会发生这种情况吗?
  • 感谢@Myst 的建议,注释掉printf 没有任何区别。我现在对 libuv 作为客户端很感兴趣,将来会尝试服务端。
  • 另一个想法,我知道这是一个不太稳定的 API,但你在调用 uv_tcp_connect 之前尝试过使用 uv_stream_set_blocking(pSock, 0) 吗?
  • 我收到错误gcc delme.c -luv /tmp/ccDEruuO.o: In function startConn': delme.c:(.text+0x282): undefined reference to uv_stream_set_blocking' collect2: error: ld returned 1 exit status,不知道为什么。
  • 原来我使用的是旧版本的 libuv(ubuntu 14.04 附带的那个)。从源代码构建 libuv1.0,我能够解析符号 uv_stream_set_blocking。不幸的是,我仍然遇到 TCP 握手顺序发生的问题,而不是像我希望的那样并行发生。

标签: c sockets networking tcp libuv


【解决方案1】:

这个例子是针对 libuv 0.1 编译的。

在它适应编译并针对 libuv1.x 运行后,它按预期工作。这是gist

libuv 0.1 和 libuv 1.0 有很大的不同。希望这个版本对那些正在寻找 libuv.c 工作示例的人有所帮助。顺便说一句,github的libuv repo中有很多很好的例子,查看“test”子目录。

【讨论】:

    猜你喜欢
    • 2013-11-10
    • 1970-01-01
    • 2018-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多