Libevent Windows IOCP 问题 - housekeeper-software/tech GitHub Wiki

问题

libevent在 windows 平台默认使用 select,如果处理大量连接,会有严重的性能问题。libevent支持IOCP,可以使得性能有显著提升。

开启 IOCP

    evthread_use_windows_threads();//这句话是必须的,否则会有问题
 
    struct event_config* cfg = event_config_new();
    event_config_set_flag(cfg,EVENT_BASE_FLAG_STARTUP_IOCP);
    SYSTEM_INFO si;
    GetSystemInfo(&si); //使用系统真实的核心数即可
    event_config_set_num_cpus_hint(cfg,si.dwNumberOfProcessors); 
    event_base *base = event_base_new_with_config(cfg); 
    event_config_free(cfg);

作为服务器

    bufferevent_setcb(bev_,
                    &OnLibeventBufferRead,
                    nullptr,
                    &OnLibeventBufferEvent,
                    this);
  int rv = bufferevent_enable(bev_, EV_WRITE | EV_READ);  

作为客户端

在连接之前,如下设置:  
  bufferevent_setcb(bev_,
                    &OnLibeventBufferRead,
                    nullptr,
                    &OnLibeventBufferEvent,
                    this);
  int rv = bufferevent_enable(bev_, EV_WRITE);

连接成功之后: 
BEV_EVENT_CONNECTED:
bufferevent_enable(bev, EV_WRITE | EV_READ);

否则会在连接成功之前会收到: BEV_EVENT_ERROR事件,但是  
EVUTIL_SOCKET_ERROR() ==0,表示没有错误。  此刻实际上发生的是windows socket报告了10057错误,libevent屏蔽了这个错误  
但依然会有错误回调。如果我们关闭连接,则连接就会失败。  

其他问题

使用 EVENT_BASE_FLAG_STARTUP_IOCP 还将导致 bufferevent_setfd 失败。
有时候,我们需要将fd从 bufferevent取出来转发到其他线程使用,EVENT_BASE_FLAG_STARTUP_IOCP 不支持这种做法。
libevent 根据指定的CPU核心数创建对应的线程池,而且事件触发可能在线程池中发生,此刻,如果不是充分考虑到多线程安全
还是不要使用 IOCP,毕竟,一般的应用用不到IOCP的高性能。服务器又很少跑在Windows上。