Tutorial :Optimizing C++ code



Question:

I'm designing classes for my application (network tool). I this base class:

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  {      // ...  }  

Many classes are based on Descriptor. I monitor sockets' events using epoll. When I want to look for events on TcpClient object I add the object's socket and pointer to this object to epoll, code:

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

I dispatch epoll events in separate thread in this way:

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++;  }  

Program is going to handle a lot of data in the epoll thread, so it mean, that virtual functions will be called many times there. I'm wondering about runtime cost of this solution.

I'm also thinking about two other implementations (however I'm not sure if the're much faster):

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;      // ...  }  

or use CRTP.

Maybe you have other idea of implementing this?


Solution:1

Unless proven otherwise, your original design looks fine to me.

The first rule of optimization is to measure first, then fix only hotspots that really exist. You'll be surprised where your code spends its time. Dwelling on the distinction between virtual functions and function pointers is almost certainly premature optimization. In both cases the compiler will generate code to jump to a function pointer, though with virtual functions the compiler will have to look up the vtable first. Write idiomatic C++ code to do what you want, then profile it if you have performance problems.

(I do have one comment about your class Descriptor: Unless you're planning on having generic data_read(), data_write(), and data_error() methods I'd recommend making them pure virtual methods.)


Solution:2

Honestly, your best bet for optimizing this code is probably to completely replace it with Boost ASIO. As described, you're essentially re-implementing the heavily scrutinized and well tested ASIO library. Unless you're absolutely certain you must roll your own I/O library, you'll probably save yourself a tremendous amount of development & optimization time by just using an existing solution.


Solution:3

Under the don't reinvent the wheel umbrella, I'd suggest looking at Boost.Asio since it offers most of the functionality you have described in your sample code.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »