Я разрабатываю классы для своего приложения (сетевой инструмент). I этот базовый класс:Оптимизация кода на С ++
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, так что это означает, что виртуальные функции будут называться много раз там. Мне интересно о стоимости выполнения этого решения.
Я также думаю о двух других реализаций (однако я не уверен, если the're гораздо быстрее):
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.
Возможно, у вас есть другие идеи по реализации этого?
Как насчет CRTP? Это немного уродливое, но не должно содержать никаких накладных расходов во время выполнения. – Goofy
Если CRTP - это вариант, не стесняйтесь идти на это. Но для низкоуровневого ввода-вывода сокетов центральный процессор не часто является узким местом. Скорее всего, это не имеет никакого значения, потому что вы просто не отправляете/не получаете столько пакетов в секунду. – jalf
+1 к jalf. Эффективный низкоуровневый ввод/вывод сокета обычно сводится к чрезвычайно жесткому и эффективному использованию потоков. Для некоторых операционных систем написание наиболее масштабируемых серверов требует даже программирования на уровне ядра! В Windows у нас есть порты завершения ввода-вывода. – stinky472