diff --git a/src/select.cpp b/src/select.cpp index 0fb1c5fb..96b1dd7b 100644 --- a/src/select.cpp +++ b/src/select.cpp @@ -401,16 +401,36 @@ zmq::select_t::fds_set_t::fds_set_t () zmq::select_t::fds_set_t::fds_set_t (const fds_set_t& other_) { +#if defined ZMQ_HAVE_WINDOWS + // On Windows we don't need to copy the whole fd_set. + // SOCKETS are continuous from the beginning of fd_array in fd_set. + // We just need to copy fd_count elements of fd_array. + // We gain huge memcpy() improvement if number of used SOCKETs is much lower than FD_SETSIZE. + memcpy (&read, &other_.read, (char *) (other_.read.fd_array + other_.read.fd_count ) - (char *) &other_.read ); + memcpy (&write, &other_.write, (char *) (other_.write.fd_array + other_.write.fd_count) - (char *) &other_.write); + memcpy (&error, &other_.error, (char *) (other_.error.fd_array + other_.error.fd_count) - (char *) &other_.error); +#else memcpy (&read, &other_.read, sizeof other_.read); memcpy (&write, &other_.write, sizeof other_.write); memcpy (&error, &other_.error, sizeof other_.error); +#endif } zmq::select_t::fds_set_t& zmq::select_t::fds_set_t::operator= (const fds_set_t& other_) { +#if defined ZMQ_HAVE_WINDOWS + // On Windows we don't need to copy the whole fd_set. + // SOCKETS are continuous from the beginning of fd_array in fd_set. + // We just need to copy fd_count elements of fd_array. + // We gain huge memcpy() improvement if number of used SOCKETs is much lower than FD_SETSIZE. + memcpy (&read, &other_.read, (char *) (other_.read.fd_array + other_.read.fd_count ) - (char *) &other_.read ); + memcpy (&write, &other_.write, (char *) (other_.write.fd_array + other_.write.fd_count) - (char *) &other_.write); + memcpy (&error, &other_.error, (char *) (other_.error.fd_array + other_.error.fd_count) - (char *) &other_.error); +#else memcpy (&read, &other_.read, sizeof other_.read); memcpy (&write, &other_.write, sizeof other_.write); memcpy (&error, &other_.error, sizeof other_.error); +#endif return *this; } diff --git a/src/zmq.cpp b/src/zmq.cpp index 2cdda058..aa7893c6 100644 --- a/src/zmq.cpp +++ b/src/zmq.cpp @@ -1110,10 +1110,14 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) // Wait for events. Ignore interrupts if there's infinite timeout. while (true) { - memcpy (&inset, &pollset_in, sizeof (fd_set)); - memcpy (&outset, &pollset_out, sizeof (fd_set)); - memcpy (&errset, &pollset_err, sizeof (fd_set)); #if defined ZMQ_HAVE_WINDOWS + // On Windows we don't need to copy the whole fd_set. + // SOCKETS are continuous from the beginning of fd_array in fd_set. + // We just need to copy fd_count elements of fd_array. + // We gain huge memcpy() improvement if number of used SOCKETs is much lower than FD_SETSIZE. + memcpy (&inset, &pollset_in , (char *) (pollset_in.fd_array + pollset_in.fd_count ) - (char *) &pollset_in ); + memcpy (&outset, &pollset_out, (char *) (pollset_out.fd_array + pollset_out.fd_count) - (char *) &pollset_out); + memcpy (&errset, &pollset_err, (char *) (pollset_err.fd_array + pollset_err.fd_count) - (char *) &pollset_err); int rc = select (0, &inset, &outset, &errset, ptimeout); if (unlikely (rc == SOCKET_ERROR)) { errno = zmq::wsa_error_to_errno (WSAGetLastError ()); @@ -1121,6 +1125,9 @@ int zmq_poll (zmq_pollitem_t *items_, int nitems_, long timeout_) return -1; } #else + memcpy (&inset, &pollset_in, sizeof (fd_set)); + memcpy (&outset, &pollset_out, sizeof (fd_set)); + memcpy (&errset, &pollset_err, sizeof (fd_set)); int rc = select (maxfd + 1, &inset, &outset, &errset, ptimeout); if (unlikely (rc == -1)) { errno_assert (errno == EINTR || errno == EBADF);