Commit 37914d1b authored by sigiesec's avatar sigiesec

Problem: get_fd_family call is expensive and called frequently for the

same fds

Solution: cache results of get_fd_family
parent 2b75a9ef
...@@ -58,6 +58,10 @@ zmq::select_t::select_t (const zmq::ctx_t &ctx_) : ...@@ -58,6 +58,10 @@ zmq::select_t::select_t (const zmq::ctx_t &ctx_) :
#endif #endif
stopping (false) stopping (false)
{ {
#if defined ZMQ_HAVE_WINDOWS
for (size_t i = 0; i < fd_family_cache_size; ++i)
fd_family_cache[i] = std::make_pair(retired_fd, 0);
#endif
} }
zmq::select_t::~select_t () zmq::select_t::~select_t ()
...@@ -466,7 +470,36 @@ bool zmq::select_t::is_retired_fd (const fd_entry_t &entry) ...@@ -466,7 +470,36 @@ bool zmq::select_t::is_retired_fd (const fd_entry_t &entry)
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
u_short zmq::select_t::get_fd_family (fd_t fd_) u_short zmq::select_t::get_fd_family (fd_t fd_)
{ {
// Use sockaddr_storage instead of sockaddr to accomodate differect structure sizes // cache the results of determine_fd_family, as this is frequently called
// for the same sockets, and determine_fd_family is expensive
size_t i;
for (i = 0; i < fd_family_cache_size; ++i)
{
const std::pair<fd_t, u_short> &entry = fd_family_cache[i];
if (entry.first == fd_)
{
return entry.second;
}
if (entry.first == retired_fd)
break;
}
std::pair<fd_t, u_short> res = std::make_pair(fd_, determine_fd_family (fd_));
if (i < fd_family_cache_size) {
fd_family_cache [i] = res;
}
else {
// just overwrite a random entry
// could be optimized by some LRU strategy
fd_family_cache [rand() % fd_family_cache_size] = res;
}
return res.second;
}
u_short zmq::select_t::determine_fd_family (fd_t fd_)
{
// Use sockaddr_storage instead of sockaddr to accommodate different structure sizes
sockaddr_storage addr = { 0 }; sockaddr_storage addr = { 0 };
int addr_size = sizeof addr; int addr_size = sizeof addr;
......
...@@ -148,8 +148,13 @@ namespace zmq ...@@ -148,8 +148,13 @@ namespace zmq
#endif #endif
#if defined ZMQ_HAVE_WINDOWS #if defined ZMQ_HAVE_WINDOWS
static const size_t fd_family_cache_size = 8;
std::pair<fd_t, u_short> fd_family_cache [fd_family_cache_size];
u_short get_fd_family (fd_t fd_);
// Socket's family or AF_UNSPEC on error. // Socket's family or AF_UNSPEC on error.
static u_short get_fd_family (fd_t fd_); static u_short determine_fd_family (fd_t fd_);
#endif #endif
// Checks if an fd_entry_t is retired. // Checks if an fd_entry_t is retired.
static bool is_retired_fd (const fd_entry_t &entry); static bool is_retired_fd (const fd_entry_t &entry);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment