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上。