我正在为我的应用程序(网络工具)设计类。在这个基类中:
class Descriptor
{
// ...
public:
virtual void data_read (void);
virtual void data_write (void);
virtual void data_error (void);
protected:
int socket_descriptor;
// ...
}
class TcpClient :
public Descriptor
{
// ...
}许多类都基于描述符。我使用epoll监视套接字的事件。当我想查找TcpClient对象上的事件时,我将该对象的套接字和指向该对象的指针添加到epoll,代码如下:
epoll_event descriptor_events;
descriptor_events.events = EPOLLIN;
descriptor_events.data.fd = this->socket_descriptor;
descriptor_events.data.ptr = this;
epoll_ctl (epoll_descriptor, EPOLL_CTL_ADD, this->socket_descriptor, &descriptor_events);我以这种方式在单独的线程中分派epoll事件:
Descriptor *descriptor (NULL);
// ...
return_value = epoll_wait (epoll_descriptor, events, 64, -1);
while (i < return_value)
{
descriptor = (Descriptor *) (events [i]).data.ptr;
if ((events [i]).events & EPOLLOUT)
descriptor->data_write ();
if ((events [i]).events & EPOLLIN)
descriptor->data_read ();
if ((events [i]).events & EPOLLERR)
descriptor->data_error ();
i++;
}程序将在epoll线程中处理大量数据,因此这意味着虚函数将被多次调用。我想知道这个解决方案的运行时成本。
我还在考虑另外两个实现(但是我不确定它们是否更快):
typedef void (*function) (Descriptor *) EventFunction;
class Descriptor
{
// ...
public:
EventFunction data_read;
EventFunction data_write;
EventFunction data_error;
protected:
Descriptor (EventFunction data_read,
EventFunction data_write,
EventFunction data_error);
int socket_descriptor;
// ...
}或者使用CRTP。
也许你有实现这个的其他想法?
发布于 2010-06-29 01:58:18
除非另有证明,否则你的原始设计在我看来很好。
优化的第一条规则是首先测量,然后只修复真正存在的热点。你会惊讶于你的代码把时间花在哪里了。详述虚函数和函数指针之间的区别几乎肯定是不成熟的优化。在这两种情况下,编译器都会生成跳转到函数指针的代码,不过对于虚函数,编译器必须首先查找vtable。编写惯用的C++代码来做您想做的事情,如果您有性能问题,则对其进行性能分析。
(我对您的类Descriptor有一点看法:除非您打算使用泛型data_read()、data_write()和data_error()方法,否则我建议将它们变成纯虚方法。)
发布于 2010-06-29 02:06:42
老实说,要优化这段代码,最好的办法可能是用Boost ASIO完全取代它。如上所述,您实际上是在重新实现经过严格检查和良好测试的ASIO库。除非您绝对确定必须使用自己的I/O库,否则只使用现有的解决方案可能会节省大量的开发和优化时间。
发布于 2010-06-29 02:04:22
在don't reinvent the wheel框架下,我建议您看看Boost.Asio,因为它提供了您在示例代码中描述的大部分功能。
https://stackoverflow.com/questions/3134800
复制相似问题