diff options
-rw-r--r-- | cpp/CHANGES | 7 | ||||
-rw-r--r-- | cpp/config/PropertyNames.def | 2 | ||||
-rw-r--r-- | cpp/src/Ice/Network.cpp | 197 | ||||
-rw-r--r-- | cpp/src/Ice/Network.h | 9 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.cpp | 4 | ||||
-rw-r--r-- | cpp/src/Ice/PropertyNames.h | 2 | ||||
-rw-r--r-- | cpp/src/Ice/TcpAcceptor.cpp | 2 | ||||
-rw-r--r-- | cpp/src/Ice/TcpConnector.cpp | 1 | ||||
-rw-r--r-- | cpp/src/Ice/TcpTransceiver.cpp | 20 | ||||
-rw-r--r-- | cpp/src/Ice/TcpTransceiver.h | 2 | ||||
-rw-r--r-- | cpp/src/IceSSL/AcceptorI.cpp | 2 | ||||
-rw-r--r-- | cpp/src/IceSSL/ConnectorI.cpp | 1 | ||||
-rw-r--r-- | cpp/src/IceSSL/TransceiverI.cpp | 17 | ||||
-rw-r--r-- | cpp/src/IceSSL/TransceiverI.h | 2 |
14 files changed, 147 insertions, 121 deletions
diff --git a/cpp/CHANGES b/cpp/CHANGES index 2059851a37c..36442c9e454 100644 --- a/cpp/CHANGES +++ b/cpp/CHANGES @@ -31,6 +31,13 @@ Changes since version 3.2.X (binary incompabible) Changes since version 3.2.0 --------------------------- +- Fixed throughput performance problem on Windows that would occur + when sending large requests. + +- Added Ice.TCP.RcvSize and Ice.TCP.SndSize properties. These + properties control the size of the TCP receive and send buffers for + the TCP and SSL transports. + - Added support for opaque endpoints. For example: opaque -t 2 -v CTEyNy4wLjAuMREnAAD/////AA== diff --git a/cpp/config/PropertyNames.def b/cpp/config/PropertyNames.def index 901f54d3d64..beb2cb8f299 100644 --- a/cpp/config/PropertyNames.def +++ b/cpp/config/PropertyNames.def @@ -185,6 +185,8 @@ Ice: Trace.Slicing UDP.RcvSize UDP.SndSize + TCP.RcvSize + TCP.SndSize UseEventLog UseSyslog Warn.AMICallback diff --git a/cpp/src/Ice/Network.cpp b/cpp/src/Ice/Network.cpp index 6e907c4bdbe..8e02559e8c6 100644 --- a/cpp/src/Ice/Network.cpp +++ b/cpp/src/Ice/Network.cpp @@ -10,6 +10,8 @@ #include <IceUtil/StaticMutex.h> #include <Ice/Network.h> #include <Ice/LocalException.h> +#include <Ice/Properties.h> // For setTcpBufSize +#include <Ice/LoggerUtil.h> // For setTcpBufSize #if defined(_WIN32) # include <winsock2.h> @@ -1297,10 +1299,66 @@ IceInternal::getLocalHosts() vector<string> result; #if defined(_WIN32) - vector<struct sockaddr_in> addrs = getLocalAddresses(); - for(unsigned int i = 0; i < addrs.size(); ++i) + try { - result.push_back(inetAddrToString(addrs[i].sin_addr)); + SOCKET fd = createSocket(false); + + vector<unsigned char> buffer; + buffer.resize(1024); + unsigned long len = 0; + DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, + &buffer[0], static_cast<DWORD>(buffer.size()), + &len, 0, 0); + if(rs == SOCKET_ERROR) + { + // + // If the buffer wasn't big enough, resize it to the + // required length and try again. + // + if(getSocketErrno() == WSAEFAULT) + { + buffer.resize(len); + rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, + &buffer[0], static_cast<DWORD>(buffer.size()), + &len, 0, 0); + } + + if(rs == SOCKET_ERROR) + { + closeSocketNoThrow(fd); + SocketException ex(__FILE__, __LINE__); + ex.error = getSocketErrno(); + throw ex; + } + } + + // + // Add the local interface addresses. + // + SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]); + for (int i = 0; i < addrs->iAddressCount; ++i) + { + result.push_back( + inetAddrToString(reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr)->sin_addr)); + } + + // + // Add the loopback interface address. + // + struct sockaddr_in addr; + memset(&addr, 0, sizeof(addr)); + addr.sin_family = AF_INET; + addr.sin_port = htons(0); + addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + result.push_back(inetAddrToString(addr.sin_addr)); + + closeSocket(fd); + } + catch(const Ice::LocalException&) + { + // + // TODO: Warning? + // } #elif defined(__linux) || defined(__APPLE__) || defined(__FreeBSD__) struct ifaddrs* ifap; @@ -1397,118 +1455,53 @@ IceInternal::getLocalHosts() return result; } -#ifdef _WIN32 -vector<struct sockaddr_in> -IceInternal::getLocalAddresses() +void +IceInternal::setTcpBufSize(SOCKET fd, const Ice::PropertiesPtr& properties, const Ice::LoggerPtr& logger) { - vector<struct sockaddr_in> result; - try - { - SOCKET fd = createSocket(false); - - vector<unsigned char> buffer; - buffer.resize(1024); - unsigned long len = 0; - DWORD rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, - &buffer[0], static_cast<DWORD>(buffer.size()), - &len, 0, 0); - if(rs == SOCKET_ERROR) - { - // - // If the buffer wasn't big enough, resize it to the - // required length and try again. - // - if(getSocketErrno() == WSAEFAULT) - { - buffer.resize(len); - rs = WSAIoctl(fd, SIO_ADDRESS_LIST_QUERY, 0, 0, - &buffer[0], static_cast<DWORD>(buffer.size()), - &len, 0, 0); - } + assert(fd != INVALID_SOCKET); - if(rs == SOCKET_ERROR) - { - closeSocketNoThrow(fd); - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; - } - } - // - // Add the local interface addresses. - // - SOCKET_ADDRESS_LIST* addrs = reinterpret_cast<SOCKET_ADDRESS_LIST*>(&buffer[0]); - for (int i = 0; i < addrs->iAddressCount; ++i) - { - result.push_back(*reinterpret_cast<struct sockaddr_in*>(addrs->Address[i].lpSockaddr)); - } - - // - // Add the loopback interface address. - // - struct sockaddr_in addr; - memset(&addr, 0, sizeof(addr)); - addr.sin_family = AF_INET; - addr.sin_port = htons(0); - addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - result.push_back(addr); + // + // By default, on Windows we use a 128KB buffer size. On Unix + // platforms, we use the system defaults. + // +#ifdef _WIN32 + const int dfltBufSize = 128 * 1024; +#else + const int dfltBufSize = 0; +#endif + Int sizeRequested; - closeSocket(fd); - } - catch(const Ice::LocalException&) + sizeRequested = properties->getPropertyAsIntWithDefault("Ice.TCP.RcvSize", dfltBufSize); + if(sizeRequested > 0) { // - // TODO: Warning? + // Try to set the buffer size. The kernel will silently adjust + // the size to an acceptable value. Then read the size back to + // get the size that was actually set. // - } - return result; -} - -bool -IceInternal::isLocalAddress(const struct sockaddr_in& addr) -{ - struct sockaddr_in addr0 = addr; - addr0.sin_port = htons(0); // Local interface addresses have the port set to 0. - - try - { - vector<struct sockaddr_in> localAddrs = getLocalAddresses(); - for(vector<struct sockaddr_in>::const_iterator p = localAddrs.begin(); p != localAddrs.end(); ++p) + setRecvBufferSize(fd, sizeRequested); + int size = getRecvBufferSize(fd); + if(size < sizeRequested) // Warn if the size that was set is less than the requested size. { - if(compareAddress(addr0, *p)) - { - return true; - } + Ice::Warning out(logger); + out << "TCP receive buffer size: requested size of " << sizeRequested << " adjusted to " << size; } } - catch(const Ice::LocalException&) + + sizeRequested = properties->getPropertyAsIntWithDefault("Ice.TCP.SndSize", dfltBufSize); + if(sizeRequested > 0) { // - // TODO: Warning? + // Try to set the buffer size. The kernel will silently adjust + // the size to an acceptable value. Then read the size back to + // get the size that was actually set. // - } - return false; -} - -bool -IceInternal::isPeerLocal(SOCKET fd) -{ - socklen_t remoteLen = static_cast<socklen_t>(sizeof(struct sockaddr_in)); - struct sockaddr_in remoteAddr; - if(getpeername(fd, reinterpret_cast<struct sockaddr*>(&remoteAddr), &remoteLen) == SOCKET_ERROR) - { - if(notConnected()) + setSendBufferSize(fd, sizeRequested); + int size = getSendBufferSize(fd); + if(size < sizeRequested) // Warn if the size that was set is less than the requested size. { - return false; - } - else - { - closeSocketNoThrow(fd); - SocketException ex(__FILE__, __LINE__); - ex.error = getSocketErrno(); - throw ex; + Ice::Warning out(logger); + out << "TCP send buffer size: requested size of " << sizeRequested << " adjusted to " << size; } } - return isLocalAddress(remoteAddr); } -#endif diff --git a/cpp/src/Ice/Network.h b/cpp/src/Ice/Network.h index f03836965c6..2d074c17dc7 100644 --- a/cpp/src/Ice/Network.h +++ b/cpp/src/Ice/Network.h @@ -15,6 +15,8 @@ #endif #include <Ice/Config.h> +#include <Ice/PropertiesF.h> // For setTcpBufSize +#include <Ice/LoggerF.h> // For setTcpBufSize #ifdef _WIN32 # include <winsock2.h> @@ -109,12 +111,7 @@ ICE_API std::string addrToString(const struct sockaddr_in&); ICE_API std::vector<std::string> getHosts(const std::string&); ICE_API std::vector<std::string> getLocalHosts(); -#ifdef _WIN32 -ICE_API std::vector<struct sockaddr_in> getLocalAddresses(); -ICE_API bool isLocalAddress(const struct sockaddr_in&); -ICE_API bool isPeerLocal(SOCKET); -#endif - +ICE_API void setTcpBufSize(SOCKET, const Ice::PropertiesPtr&, const Ice::LoggerPtr&); ICE_API int getSocketErrno(); ICE_API std::string inetAddrToString(const struct in_addr&); diff --git a/cpp/src/Ice/PropertyNames.cpp b/cpp/src/Ice/PropertyNames.cpp index 0744d7d004e..20b4b620765 100644 --- a/cpp/src/Ice/PropertyNames.cpp +++ b/cpp/src/Ice/PropertyNames.cpp @@ -7,7 +7,7 @@ // // ********************************************************************** -// Generated by makeprops.py from file `../config/PropertyNames.def', Tue May 15 12:31:29 2007 +// Generated by makeprops.py from file `../config/PropertyNames.def', Wed May 23 14:21:55 2007 // IMPORTANT: Do not edit this file -- any edits made here will be lost! @@ -87,6 +87,8 @@ const char* IceInternal::PropertyNames::IceProps[] = "Ice.Trace.Slicing", "Ice.UDP.RcvSize", "Ice.UDP.SndSize", + "Ice.TCP.RcvSize", + "Ice.TCP.SndSize", "Ice.UseEventLog", "Ice.UseSyslog", "Ice.Warn.AMICallback", diff --git a/cpp/src/Ice/PropertyNames.h b/cpp/src/Ice/PropertyNames.h index 30edd10e84e..9acdaea97c0 100644 --- a/cpp/src/Ice/PropertyNames.h +++ b/cpp/src/Ice/PropertyNames.h @@ -7,7 +7,7 @@ // // ********************************************************************** -// Generated by makeprops.py from file `../config/PropertyNames.def', Tue May 15 12:31:29 2007 +// Generated by makeprops.py from file `../config/PropertyNames.def', Wed May 23 14:21:55 2007 // IMPORTANT: Do not edit this file -- any edits made here will be lost! diff --git a/cpp/src/Ice/TcpAcceptor.cpp b/cpp/src/Ice/TcpAcceptor.cpp index 193aefe8175..2ffb6fd5a0d 100644 --- a/cpp/src/Ice/TcpAcceptor.cpp +++ b/cpp/src/Ice/TcpAcceptor.cpp @@ -64,6 +64,7 @@ IceInternal::TcpAcceptor::accept(int timeout) { SOCKET fd = doAccept(_fd, timeout); setBlock(fd, false); + setTcpBufSize(fd, _instance->initializationData().properties, _logger); if(_traceLevels->network >= 1) { @@ -119,6 +120,7 @@ IceInternal::TcpAcceptor::TcpAcceptor(const InstancePtr& instance, const string& _fd = createSocket(false); setBlock(_fd, false); getAddress(host, port, _addr); + setTcpBufSize(_fd, _instance->initializationData().properties, _logger); if(_traceLevels->network >= 2) { Trace out(_logger, _traceLevels->networkCat); diff --git a/cpp/src/Ice/TcpConnector.cpp b/cpp/src/Ice/TcpConnector.cpp index 935aaa9a84a..4effb9ff4d6 100644 --- a/cpp/src/Ice/TcpConnector.cpp +++ b/cpp/src/Ice/TcpConnector.cpp @@ -30,6 +30,7 @@ IceInternal::TcpConnector::connect(int timeout) SOCKET fd = createSocket(false); setBlock(fd, false); + setTcpBufSize(fd, _instance->initializationData().properties, _logger); doConnect(fd, _addr, timeout); if(_traceLevels->network >= 1) diff --git a/cpp/src/Ice/TcpTransceiver.cpp b/cpp/src/Ice/TcpTransceiver.cpp index 541843223b7..200778293c6 100644 --- a/cpp/src/Ice/TcpTransceiver.cpp +++ b/cpp/src/Ice/TcpTransceiver.cpp @@ -85,9 +85,9 @@ IceInternal::TcpTransceiver::write(Buffer& buf, int timeout) // // Limit packet size to avoid performance problems on WIN32 // - if(_isPeerLocal && packetSize > 64 * 1024) + if(packetSize > _maxPacketSize) { - packetSize = 64 * 1024; + packetSize = _maxPacketSize; } #endif @@ -358,12 +358,22 @@ IceInternal::TcpTransceiver::TcpTransceiver(const InstancePtr& instance, SOCKET _stats(instance->initializationData().stats), _fd(fd), _desc(fdToString(fd)) -#ifdef _WIN32 - , _isPeerLocal(isPeerLocal(fd)) -#endif { FD_ZERO(&_rFdSet); FD_ZERO(&_wFdSet); + +#ifdef _WIN32 + // + // On Windows, limiting the buffer size is important to prevent + // poor throughput performances when transfering large amount of + // data. See Microsoft KB article KB823764. + // + _maxPacketSize = IceInternal::getSendBufferSize(_fd) / 2; + if(_maxPacketSize < 512) + { + _maxPacketSize = 0; + } +#endif } IceInternal::TcpTransceiver::~TcpTransceiver() diff --git a/cpp/src/Ice/TcpTransceiver.h b/cpp/src/Ice/TcpTransceiver.h index a6a7abbdb29..fe4f78d1724 100644 --- a/cpp/src/Ice/TcpTransceiver.h +++ b/cpp/src/Ice/TcpTransceiver.h @@ -54,7 +54,7 @@ private: const std::string _desc; #ifdef _WIN32 - const bool _isPeerLocal; + int _maxPacketSize; #endif }; diff --git a/cpp/src/IceSSL/AcceptorI.cpp b/cpp/src/IceSSL/AcceptorI.cpp index 2bd7a3e105c..b2fec924caa 100644 --- a/cpp/src/IceSSL/AcceptorI.cpp +++ b/cpp/src/IceSSL/AcceptorI.cpp @@ -77,6 +77,7 @@ IceSSL::AcceptorI::accept(int timeout) SOCKET fd = IceInternal::doAccept(_fd, timeout); IceInternal::setBlock(fd, false); + IceInternal::setTcpBufSize(fd, _instance->communicator()->getProperties(), _logger); BIO* bio = BIO_new_socket(static_cast<int>(fd), BIO_CLOSE); if(!bio) @@ -155,6 +156,7 @@ IceSSL::AcceptorI::AcceptorI(const InstancePtr& instance, const string& adapterN _fd = IceInternal::createSocket(false); IceInternal::setBlock(_fd, false); IceInternal::getAddress(host, port, _addr); + IceInternal::setTcpBufSize(_fd, _instance->communicator()->getProperties(), _logger); if(_instance->networkTraceLevel() >= 2) { Trace out(_logger, _instance->networkTraceCategory()); diff --git a/cpp/src/IceSSL/ConnectorI.cpp b/cpp/src/IceSSL/ConnectorI.cpp index 8a68c3559c3..ffda1471012 100644 --- a/cpp/src/IceSSL/ConnectorI.cpp +++ b/cpp/src/IceSSL/ConnectorI.cpp @@ -41,6 +41,7 @@ IceSSL::ConnectorI::connect(int timeout) SOCKET fd = IceInternal::createSocket(false); IceInternal::setBlock(fd, false); + IceInternal::setTcpBufSize(fd, _instance->communicator()->getProperties(), _logger); IceInternal::doConnect(fd, _addr, timeout); // This static_cast is necessary due to 64bit windows. There SOCKET is a non-int type. diff --git a/cpp/src/IceSSL/TransceiverI.cpp b/cpp/src/IceSSL/TransceiverI.cpp index 7f51ac52c76..705f02e2071 100644 --- a/cpp/src/IceSSL/TransceiverI.cpp +++ b/cpp/src/IceSSL/TransceiverI.cpp @@ -87,9 +87,9 @@ IceSSL::TransceiverI::write(IceInternal::Buffer& buf, int timeout) // // Limit packet size to avoid performance problems on WIN32 // - if(_isPeerLocal && packetSize > 64 * 1024) + if(packetSize > _maxPacketSize) { - packetSize = 64 * 1024; + packetSize = _maxPacketSize; } #endif @@ -541,10 +541,19 @@ IceSSL::TransceiverI::TransceiverI(const InstancePtr& instance, SSL* ssl, SOCKET _adapterName(adapterName), _incoming(incoming), _desc(IceInternal::fdToString(fd)) +{ #ifdef _WIN32 - , _isPeerLocal(IceInternal::isPeerLocal(fd)) + // + // On Windows, limiting the buffer size is important to prevent + // poor throughput performances when transfering large amount of + // data. See Microsoft KB article KB823764. + // + _maxPacketSize = IceInternal::getSendBufferSize(_fd) / 2; + if(_maxPacketSize < 512) + { + _maxPacketSize = 0; + } #endif -{ } IceSSL::TransceiverI::~TransceiverI() diff --git a/cpp/src/IceSSL/TransceiverI.h b/cpp/src/IceSSL/TransceiverI.h index 46daa6d9570..d20915ea5f2 100644 --- a/cpp/src/IceSSL/TransceiverI.h +++ b/cpp/src/IceSSL/TransceiverI.h @@ -63,7 +63,7 @@ private: const std::string _desc; #ifdef _WIN32 - const bool _isPeerLocal; + int _maxPacketSize; #endif }; typedef IceUtil::Handle<TransceiverI> TransceiverIPtr; |